springboot项目参数校验及自定义校验注解

常用参数校验注解:

  • @AssertFalse 所注解的元素必须是Boolean类型,且值为false
  • @AssertTrue 所注解的元素必须是Boolean类型,且值为true
  • @DecimalMax 所注解的元素必须是数字,且值小于等于给定的值
  • @DecimalMin 所注解的元素必须是数字,且值大于等于给定的值
  • @Digits 所注解的元素必须是数字,且值必须是指定的位数
  • @Future 所注解的元素必须是将来某个日期
  • @Max 所注解的元素必须是数字,且值小于等于给定的值
  • @Min 所注解的元素必须是数字,且值小于等于给定的值
  • @Range 所注解的元素需在指定范围区间内
  • @NotNull 所注解的元素值不能为null
  • @NotBlank 所注解的元素值有内容
  • @Null 所注解的元素值为null
  • @Past 所注解的元素必须是某个过去的日期
  • @PastOrPresent 所注解的元素必须是过去某个或现在日期
  • @Pattern 所注解的元素必须满足给定的正则表达式
  • @Size 所注解的元素必须是String、集合或数组,且长度大小需保证在给定范围之内
  • @Email 所注解的元素需满足Email格式

1. @NotNull,@NotEmpty,@NotBlank的区别

@NotNull:不能为null,作用于对象

@NotEmpty:不能为null且长度必须大于0,作用于string(不能为"",可以为" ")、集合、map、 数组

@NotBlank:不能为null且不能为""、" ",作用于string

2. get请求参数校验

直接将注解用在参数前面就行,举例:

@GetMapping("/get-user")
public ResultResponse<UserVO> getUser(@NotNull (message = "用户Id不能为null") Long userId) {
    return ResultResponse.success(new UserVO());
}

不带参数请求,返回结果如下:

这个报错显然没有封装,所以我们需要对ConstraintViolationException进行封装

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultResponse handle(ValidationException exception) {
        List<String> message = new ArrayList<>();
        if(exception instanceof ConstraintViolationException){
            ConstraintViolationException exs = (ConstraintViolationException) exception;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                message.add(item.getMessage());
            }
        }
        return ResultResponse.fail("-1", JSON.toJSONString(message));
    }
}

再次不带参数请求,返回结果如下:

3. post请求参数校验

方法实体参数前加注解@Validated

@PostMapping("/insertUser")
    public ResultResponse<Boolean> insertUser(@RequestBody @Validated UserVO userVO) {
        return ResultResponse.success(true);
    }

实体字段上加校验注解

	@NotNull(message = "用户id不能为空")
    private Long userId;

    @NotBlank(message = "用户名称不能为空")
    private String userName;

    private Integer age;
    private String address;
    private ChildVO childVO;

注意:若是校验对象集合,要使用@Valid注解

使用post请求访问不带参数访问,返回错误如下:

显然,这个校验错误,我们也需要封装一下

@ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultResponse handle(MethodArgumentNotValidException exception) {
        List<String> message = new ArrayList<>();
        if(exception instanceof MethodArgumentNotValidException){
            MethodArgumentNotValidException exs = (MethodArgumentNotValidException) exception;
            BindingResult bindingResult = exs.getBindingResult();
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            for (ObjectError item : allErrors) {
                message.add(item.getDefaultMessage());
            }
        }
        return ResultResponse.fail("-1", JSON.toJSONString(message));
    }

封装之后,再次访问,报错如下:

4. 快速失败模式

  • validation默认是普通模式,即返回所有校验错误的信息

  • 快速失败模式,即有一个错误就返回

    快速失败模式配置方式:

    @Configuration
    public class ValidatorConf {
        @Bean
        public Validator validator() {
            ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                    .configure()
                    .failFast( true )
                    .buildValidatorFactory();
            Validator validator = validatorFactory.getValidator();
            return validator;
        }
    }
    

5. 分组校验

有时方法都用同一个实体做参数检验,可能有些参数是必要的,有些是不要的,这时可以分组校验,在校验注解中使用groups分组,方法中校验指定分组,可以指定多个分组

6. 自定义校验注解

eg:添加一个参数必须为偶数的注解

步骤:

1. 新建注解,添加message、groups、payload参数
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = EvenNumberValidatorImpl.class)
public @interface EvenNumber {
    int value() default 0;

    String message() default "参数必须为偶数";

    Class[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2. 新建注解实现类,实现ConstraintValidator
public class EvenNumberValidatorImpl implements ConstraintValidator<EvenNumber, Integer> {
      private int value;
  
      @Override
      public void initialize(EvenNumber constraintAnnotation) {
          this.value = constraintAnnotation.value();
      }
  
      @Override
      public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
          if (integer != null) {
              return integer % 2 == 0;
          }
          return false;
      }
  }
3. 在字段上使用
@EvenNumber(message = "号码必须为偶数")
private Integer number;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值