快速校驗實體類時,@Valid,@Validated,@NotNull註解無效的解決
校驗實體類參數內容不能為空時使用註解校驗無效
使用@valid註解首先引入依賴
如果是SpringBoot項目,引入web開發包,就不需要再單獨引入@valid依賴瞭、因為他存在於Web開發包中的最核心之中
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.5.RELEASE</version> </dependency>
如果不是SpringBoot項目,要在Maven的Pom中顯式引入@valid依賴
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.4.1.Final</version> </dependency>
校驗實體類大部分人使用的方法肯定都是controller層裡面拿出來判斷是否為空,其實可以直接通過實體類中的註釋@NotNull直接校驗,如圖
但經過我的實驗,不知道什麼原因,在我的項目中並沒有起到作用,解決如下
1、更換方法入參類型
在網上看到@Valid是可以用在方法、構造函數、方法參數和成員屬性(字段)上,而我一開始controller層中使用的是json接收的,轉換成實體類後再校驗的,如圖
修改如下:在controller接收數據時直接以對象接收,在入口中直接以註解進行校驗
2、錯誤內容過多
此時對象字段校驗生效,但是出錯時返回的是很凌亂的內容,如圖:
3、使用對象接收錯誤內容,按自己要求輸出
上面的圖片可看出,返回內容中defaultMessage就是想要輸出的內容,所以在方法中添加一個接收錯誤信息的類型為BindingResult的對象,如果對象有數據,則輸出錯誤數據,如圖:
另一層面的實現瞭實體類的參數校驗,大傢如果有更好的方法可以留言交流
springboot 校驗機制 @Validated @Valid
1、探究原因
在開發的過程中一直迷惑 @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 包下
2、使用@Validated 實現校驗機制
情景一: 查詢參數是一個實體,Get 請求,在不添加任何註解的情況下,查詢是正常的,實體參數字段都為null
現在需求 id 字段不能為空,在實體id 字段標記 @NotNull ,繼續查詢,發現註解沒有生效
經過測試,隻有請求實體參數列表前加@Validated 才會生效,即使@Validated 加在類上也無法生效
情景二: 查詢參數是基本或者引用類型字段,參數列表中加入 @NutNull 修改該字段。發現無法生效
經過測試:隻有全局類上加@Validated 才會生效,即使參數列表中加入 @Validated 也無法生效
產生異常也有所不同:在校驗生效的情況下,實體類校驗產生的異常是:BindException , 而參數列表產生的異常是:ConstraintViolationException
3、使用@Valid 實現校驗機制
場景一:與上述一致,隻有@Valid 作用在參數列表前才會生效
場景二:@Valida 不管是左右在參數列表還是類上,都無法生效。隻能使用@Validated 全局設置
結論:暫不清楚@Valid 設計出現的原因,所以的校驗@Validate 均可以實現
附加全局異常捕獲:
@RestControllerAdvice public class GlobalException { @ExceptionHandler({BindException.class}) public RespResult validationException(BindException exception){ List<ObjectError> errors = exception.getAllErrors(); if(!CollectionUtils.isEmpty(errors)){ StringBuilder sb = new StringBuilder(); errors.forEach(e->sb.append(e.getDefaultMessage()).append(",")); return new RespResult(400, sb.toString()); } return new RespResult(500, exception.getLocalizedMessage()); } @ExceptionHandler({ConstraintViolationException.class}) public RespResult constraintViolationException(ConstraintViolationException exception){ Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations(); if(!CollectionUtils.isEmpty(constraintViolations)){ StringBuilder sb = new StringBuilder(); constraintViolations.forEach(e->sb.append(e.getMessage()).append(",")); return new RespResult(400, sb.toString()); } return new RespResult(500, exception.getLocalizedMessage()); } }
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 詳解Spring中@Valid和@Validated註解用法
- SpringBoot 中使用 Validation 校驗參數的方法詳解
- Java中的Valid和Validated的比較內容
- Spring 使用Validation 驗證框架的問題詳解
- 參數校驗Spring的@Valid註解用法解析