前言

前后端拆散开发,常常用json数据格式进行交互,对立的响应数据格式,造成对立标准,能够大大不便前后端人员的开发。

Response数据封装

  • 编码枚举类 ResultCode.java
public enum ResResultCode {    /**     * 胜利     */    SUCCESS(200, "ok"),    /**     * 申请谬误     */    BAD_REQUEST(400, "申请参数谬误"),    /**     * 未登录受权     */    UNAUTHORIZED(401, "有效令牌"),    /**     * 权限有余     */    FORBIDDEN(403, "权限有余"),    /**     * 服务器谬误     */    FAILED(500, "server error"),    /**     * 业务异样     */    BIZ_ERROR(600, "业务异样");    private int status;    private String message;    ResResultCode(int status, String message) {        this.status = status;        this.message = message;    }    public int getStatus() {        return status;    }    public String getMessage() {        return message;    }    public void setStatus(int status) {        this.status = status;    }    public void setMessage(String message) {        this.message = message;    }}
  • json数据封装类
@Datapublic class ResResult {    /**     * 响应编码     */    private int code;    /**     * 响应信息     */    private String msg;    /**     * 响应数据     */    private Object data;    public ResResult(int code, String msg) {        this.code = code;        this.msg = msg;    }    public ResResult(int code, String msg, Object data) {        this.code = code;        this.msg = msg;        this.data = data;    }    public static ResResult success() {        return new ResResult(ResResultCode.SUCCESS.getStatus(), ResResultCode.SUCCESS.getMessage(), null);    }    public static ResResult success(Object data) {        return new ResResult(ResResultCode.SUCCESS.getStatus(), ResResultCode.SUCCESS.getMessage(), data);    }    public static ResResult failure() {        return new ResResult(ResResultCode.FAILED.getStatus(), ResResultCode.FAILED.getMessage());    }    public static ResResult failure(ResResultCode ResResultCode) {        return new ResResult(ResResultCode.getStatus(), ResResultCode.getMessage());    }}

自定义异样类

  • BizErrorException.java 用来抛出业务异样
public class BizErrorException extends RuntimeException {    private ResResultCode resResultCode;    private String message;    public BizErrorException(ResResultCode resResultCode) {        this.resResultCode = resResultCode;    }    public BizErrorException(ResResultCode resResultCode, String message) {        this.resResultCode = resResultCode;        this.message = message;    }    public ResResultCode getResResultCode() {        return resResultCode;    }    @Override    public String getMessage() {        return message;    }    public void setMessage(String message) {        this.message = message;    }}
  • BadRequestException.java 用来抛出申请参数异样
public class BadRequestException extends RuntimeException {    public BadRequestException() {    }    public BadRequestException(String message) {        super(message);    }}

全局申请参数校验

尽管spring提供了@Valid能够进行申请参数的校验

留神一个坑:hibernate-validator在springboot 2.3之后就须要手动引入了,不再主动配置。

<!-- springboot 2.3之后隐没的hibernate-validator解决办法--><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-validation</artifactId></dependency>

作为一个前后端拆散我的项目,并且接口并不对外裸露,后端每个接口调用都创立一个vo类,显然是十分麻烦的,这边就不必这种形式

这里就抉择了一个偷懒的办法,就是利用Knife4j动静申请参数 再加上AOP 进行校验。具体实现步骤:

  1. 引入AOP依赖
<!-- AOP --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-aop</artifactId></dependency>
  1. 新建一个aop类 ReqValidateAop.java

在执行每个@DynamicParameters注解润饰的接口是进行校验,对每个required = true 的参数进行校验。

/** * 对含有@DynamicParameters动静参数的接口 进行申请参数校验 */@Aspect@Component@Slf4jpublic class ReqValidateAop {    /**     * 所有办法: @Pointcut("execution(* com.ify.formwork.web.controller.*.*.*(..))")     * 含有@DynamicParameters注解:@Pointcut("@annotation(com.github.xiaoymin.knife4j.annotations.DynamicParameters)")     */    @Pointcut("@annotation(com.github.xiaoymin.knife4j.annotations.DynamicParameters)")    public void paramValidate() {    }    @Before("paramValidate()")    public void before(JoinPoint joinPoint) throws BadRequestException {        List<String> errList = new ArrayList<>();        Object[] objects = joinPoint.getArgs();        JSONObject param = (JSONObject) objects[0];        // 获取以后办法        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();        Method method = methodSignature.getMethod();        // 获取办法@DynamicParameters properties        DynamicParameters annotation = method.getAnnotation(DynamicParameters.class);        List<DynamicParameter> list = Arrays.asList(annotation.properties());        for (DynamicParameter dynamicParameter : list) {            // 必传参数校验            if (dynamicParameter.required()) {                Object o = param.get(dynamicParameter.name());                // 申请参数为null 或申请参数为字符串为空串                boolean badRequest = (null == o) || (o instanceof String && StrUtil.isEmpty((String) o));                if (badRequest) {                    errList.add(dynamicParameter.name() + "不能为空");                }            }        }        if (!errList.isEmpty()) {            throw new BadRequestException(StrUtil.join(",", errList));        }    }}

全局异样拦挡解决

对服务抛出的异样进行接管,对立解决返回给前端

@Slf4j@RestControllerAdvicepublic class GlobalExceptionHandler {    /***     * 性能形容:  捕捉申请参数异样 ReqValidateAop.java 自定义校验形式     */    @ResponseStatus(HttpStatus.BAD_REQUEST)    @ExceptionHandler(BadRequestException.class)    public ResResult handleBadRequestException(BadRequestException e) {        return new ResResult(ResResultCode.BAD_REQUEST.getStatus(), e.getMessage());    }    /**     * 性能形容:  捕捉申请参数异样 @valid校验参数形式 (如果采纳这种形式的话能够进行应用)     */    @ResponseStatus(HttpStatus.BAD_REQUEST)    @ExceptionHandler(MethodArgumentNotValidException.class)    public ResResult handleBadRequestException(MethodArgumentNotValidException e) {        BindingResult bindingResult = e.getBindingResult();        List<String> errors = new ArrayList<>();        for (FieldError fieldError : bindingResult.getFieldErrors()) {            errors.add(fieldError.getField() + fieldError.getDefaultMessage());        }        return new ResResult(ResResultCode.BAD_REQUEST.getStatus(), StrUtil.join("|", errors));    }    /**     * 业务异样捕捉 对立返回500状态,具体信息封装在msg里     */    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)    @ExceptionHandler(BizErrorException.class)    public ResResult handleBizErrorException(BizErrorException e) {        if (StrUtil.isNotEmpty(e.getMessage())) {            e.getResResultCode().setMessage(e.getMessage());        }        return ResResult.failure(e.getResResultCode());    }    /**     * 性能形容: 异样对立返回, 对立返回500状态     */    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)    @ExceptionHandler(Exception.class)    public ResResult handleException(Exception e) {        log.error("server error = {}", e.getMessage());        return ResResult.failure();    }}

后端的对立数据封装差不多就这样了。。。