springboot集成validation-api,优雅的判断入参

1.背景:方法入参过多,用StringUtils.isBlank判断很麻烦,而且很不美观,如下图

  @PostMapping("demo")
    void demo(@RequestBody OrderEntity orderEntity){
        if(StringUtils.isBlank(orderEntity.getOrderId())){
            log.info("orderID不能为空。。。");
            return;
        }
        if(StringUtils.isBlank(orderEntity.getOrderStatus())){
            log.info("orderStatus不能为空。。。");
            return;
        }
        log.info("测试方法demo。。。");
    }

2.接下来我们了解下validation-api,如何判断入参

2.1首先导入相关依赖:

     <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>2.0.1.Final</version>
    </dependency>

2.2实体类加上注解

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class OrderEntity {
    @NotBlank(message = "订单号不能为空")
    String orderId;
    @NotNull(message = "订单状态不能为空")
    Integer orderStatus;
}

2.3测试controller,加上@Valid注解

@Slf4j
@RestController
@RequestMapping("test")
public class TestController {

    @PostMapping("demo")
    BaseResponse<?> demo(@Valid @RequestBody OrderEntity orderEntity){
        log.info("测试方法demo。。。");
        return new BaseResponse<>();
    }
}

2.4postman测试故意不传参数

代码抛出异常,返回一个json数据格式,其中"defaultMessage": "订单号不能为空",这才是我们想要返回给前端的信息,而不是整个json。

2.5 利用aop捕获异常

写一个异常类GlobalExceptionHandler ,利用@ControllerAdvice和@ExceptionHandler捕获异常

package com.front.aop;

import com.front.common.enums.ErrorCodeEnum;
import com.front.common.response.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 忽略参数异常处理器
     * @param e 忽略参数异常
     * @return BaseResponse
     */

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public BaseResponse<?> parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        log.error("忽略参数异常处理器", e);
        return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode(), "请求参数 " + e.getParameterName() + " 不能为空");
    }

    /**
     * 缺少请求体异常处理器
     * @param e 缺少请求体异常
     * @return BaseResponse
     */

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public BaseResponse<?> parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        log.error("", e);
        return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode(), "参数体不能为空");
    }

    /**
     * 参数效验异常处理器
     * @param e 参数验证异常
     * @return ResponseInfo
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public BaseResponse<?> parameterExceptionHandler(MethodArgumentNotValidException e) {
        log.error("参数效验异常处理器", e);
        // 获取异常信息
        BindingResult exceptions = e.getBindingResult();
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                // 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
                FieldError fieldError = (FieldError) errors.get(0);
                return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode(), fieldError.getDefaultMessage());
            }
        }
        return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode());
    }

    /**
     * 自定义参数错误异常处理器
     * @param e 自定义参数
     * @return ResponseInfo
     */

    /*@ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({BusinessException.class})
    @ResponseBody
    public BaseResponse paramExceptionHandler(ParamaErrorException e) {
        log.error("", e);
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        if (!StringUtils.isEmpty(e.getMessage())) {
            return new BaseResponse(ErrorCodeEnum.FAIL.getCode(), e.getMessage());
        }
        return new BaseResponse(ErrorCodeEnum.FAIL);
    }*/


    /**
     * 其他异常
     * @param e
     * @return
     */

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({Exception.class})
    @ResponseBody
    public BaseResponse<?> otherExceptionHandler(Exception e) {
        log.error("其他异常", e);
        // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
        if (!StringUtils.isEmpty(e.getMessage())) {
            return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode(), e.getMessage());
        }
        return new BaseResponse<>(ErrorCodeEnum.FAIL.getCode());
    }

}

BaseResponse:

package com.front.common.response;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

@Data
@AllArgsConstructor
public class BaseResponse<T> implements Serializable {
    private static final String SUCCESS = "SUCCESS";

    private static final String FAIL = "FAIL";

    private String code="200";

    private String message="操作成功";

    private T data;

    public BaseResponse() {
    }

    public BaseResponse(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public BaseResponse(String code) {
        this.code = code;
    }

    public void setData(T data) {
        this.data = data;
    }
}

ErrorCodeEnum :

package com.front.common.enums;

import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
public enum ErrorCodeEnum {
    FAIL("400", "失败");
    final String code;
    final String detail;
    public String getCode() {
        return this.code;
    }

    public String getDetail() {
        return this.detail;
    }
}

2.6启动项目postman再测试一次

至此完结!!!