springboot 校验机制 @Validated @Valid

一、探究原因

在开发的过程中一直迷惑 @Validated 与 @Valid 的用法,有时候是@Validated ,有时候是@Valid  。虽然能够实现校验,但是还是不够明确何时能够生效,不了解他生效的情况

首先定位2个注解所属的包:

@Validated  在 spring-context 包下属于spring 提供的核心包

@Valid 在 validation-api 包下  2.0.2 版本

@Validated 是spring 核心包,是每个项目都有的,那么 api 是如何引入的? 查看maven 依赖

 原来是在引入 Spring-boot-start-web 的时候,就引入了该依赖

两个注解存在不同的包,而@NotNull ,@Null ,@Size ,@Max 等校验注解是哪里的呢?

 这些注解都是在 api 包下

二、使用@Validated 实现校验机制

情景一: 查询参数是一个实体,Get 请求,在不添加任何注解的情况下,查询是正常的,实体参数字段都为null 

 现在需求 id  字段不能为空,在实体id 字段标记 @NotNull ,继续查询,发现注解没有生效

经过测试,只有请求实体参数列表前加@Validated 才会生效,即使@Validated 加在类上也无法生效

情景二: 查询参数是基本或者引用类型字段,参数列表中加入 @NutNull 修改该字段。发现无法生效

经过测试:只有全局类上加@Validated 才会生效,即使参数列表中加入 @Validated 也无法生效

产生异常也有所不同:在校验生效的情况下,实体类校验产生的异常是:BindException , 而参数列表产生的异常是: ConstraintViolationException

三、使用@Valid 实现校验机制

场景一:与上述一致,只有@Valid 作用在参数列表前才会生效

场景二:@Valida 不管是左右在参数列表还是类上,都无法生效。只能使用@Validated 全局设置

结论:暂不清楚@Valid 设计出现的原因,所以的校验@Validate 均可以实现

附加全局异常捕获:

 1 @RestControllerAdvice
 2 public class GlobalException {
 3 
 4 
 5     @ExceptionHandler({BindException.class})
 6     public RespResult validationException(BindException exception){
 7         List<ObjectError> errors =  exception.getAllErrors();
 8         if(!CollectionUtils.isEmpty(errors)){
 9             StringBuilder sb = new StringBuilder();
10             errors.forEach(e->sb.append(e.getDefaultMessage()).append(","));
11             return new RespResult(400, sb.toString());
12         }
13         return new RespResult(500, exception.getLocalizedMessage());
14     }
15 
16     @ExceptionHandler({ConstraintViolationException.class})
17     public RespResult constraintViolationException(ConstraintViolationException exception){
18         Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
19         if(!CollectionUtils.isEmpty(constraintViolations)){
20             StringBuilder sb = new StringBuilder();
21             constraintViolations.forEach(e->sb.append(e.getMessage()).append(","));
22             return new RespResult(400, sb.toString());
23         }
24         return new RespResult(500, exception.getLocalizedMessage());
25     }
26 
27 }
原文地址:https://www.cnblogs.com/bytecodebuffer/p/13695361.html