一、探究原因
在開發的過程中一直迷惑 @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 }