快速校驗(yàn)實(shí)體類時(shí),@Valid,@Validated,@NotNull注解無效的解決
校驗(yàn)實(shí)體類參數(shù)內(nèi)容不能為空時(shí)使用注解校驗(yàn)無效
使用@valid注解首先引入依賴
如果是SpringBoot項(xiàng)目,引入web開發(fā)包,就不需要再單獨(dú)引入@valid依賴了、因?yàn)樗嬖谟赪eb開發(fā)包中的最核心之中
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.5.RELEASE</version> </dependency>
如果不是SpringBoot項(xiàng)目,要在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>
校驗(yàn)實(shí)體類大部分人使用的方法肯定都是controller層里面拿出來判斷是否為空,其實(shí)可以直接通過實(shí)體類中的注釋@NotNull直接校驗(yàn),如圖
但經(jīng)過我的實(shí)驗(yàn),不知道什么原因,在我的項(xiàng)目中并沒有起到作用,解決如下
1、更換方法入?yún)㈩愋?/h3>
在網(wǎng)上看到@Valid是可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上,而我一開始controller層中使用的是json接收的,轉(zhuǎn)換成實(shí)體類后再校驗(yàn)的,如圖
修改如下:在controller接收數(shù)據(jù)時(shí)直接以對(duì)象接收,在入口中直接以注解進(jìn)行校驗(yàn)
2、錯(cuò)誤內(nèi)容過多
此時(shí)對(duì)象字段校驗(yàn)生效,但是出錯(cuò)時(shí)返回的是很凌亂的內(nèi)容,如圖:
3、使用對(duì)象接收錯(cuò)誤內(nèi)容,按自己要求輸出
上面的圖片可看出,返回內(nèi)容中defaultMessage就是想要輸出的內(nèi)容,所以在方法中添加一個(gè)接收錯(cuò)誤信息的類型為BindingResult的對(duì)象,如果對(duì)象有數(shù)據(jù),則輸出錯(cuò)誤數(shù)據(jù),如圖:
另一層面的實(shí)現(xiàn)了實(shí)體類的參數(shù)校驗(yàn),大家如果有更好的方法可以留言交流
springboot 校驗(yàn)機(jī)制 @Validated @Valid
1、探究原因
在開發(fā)的過程中一直迷惑 @Validated 與 @Valid 的用法,有時(shí)候是@Validated ,有時(shí)候是@Valid 。雖然能夠?qū)崿F(xiàn)校驗(yàn),但是還是不夠明確何時(shí)能夠生效,不了解他生效的情況
首先定位2個(gè)注解所屬的包:
@Validated 在 spring-context 包下屬于spring 提供的核心包
@Valid 在 validation-api 包下 2.0.2 版本
@Validated 是spring 核心包,是每個(gè)項(xiàng)目都有的,那么 api 是如何引入的? 查看maven 依賴
原來是在引入 Spring-boot-start-web 的時(shí)候,就引入了該依賴
兩個(gè)注解存在不同的包,而@NotNull ,@Null ,@Size ,@Max 等校驗(yàn)注解是哪里的呢?
這些注解都是在 api 包下
2、使用@Validated 實(shí)現(xiàn)校驗(yàn)機(jī)制
情景一: 查詢參數(shù)是一個(gè)實(shí)體,Get 請(qǐng)求,在不添加任何注解的情況下,查詢是正常的,實(shí)體參數(shù)字段都為null
現(xiàn)在需求 id 字段不能為空,在實(shí)體id 字段標(biāo)記 @NotNull ,繼續(xù)查詢,發(fā)現(xiàn)注解沒有生效
經(jīng)過測(cè)試,只有請(qǐng)求實(shí)體參數(shù)列表前加@Validated 才會(huì)生效,即使@Validated 加在類上也無法生效
情景二: 查詢參數(shù)是基本或者引用類型字段,參數(shù)列表中加入 @NutNull 修改該字段。發(fā)現(xiàn)無法生效
經(jīng)過測(cè)試:只有全局類上加@Validated 才會(huì)生效,即使參數(shù)列表中加入 @Validated 也無法生效
產(chǎn)生異常也有所不同:在校驗(yàn)生效的情況下,實(shí)體類校驗(yàn)產(chǎn)生的異常是:BindException , 而參數(shù)列表產(chǎn)生的異常是:ConstraintViolationException
3、使用@Valid 實(shí)現(xiàn)校驗(yàn)機(jī)制
場(chǎng)景一:與上述一致,只有@Valid 作用在參數(shù)列表前才會(huì)生效
場(chǎng)景二:@Valida 不管是左右在參數(shù)列表還是類上,都無法生效。只能使用@Validated 全局設(shè)置
結(jié)論:暫不清楚@Valid 設(shè)計(jì)出現(xiàn)的原因,所以的校驗(yàn)@Validate 均可以實(shí)現(xiàn)
附加全局異常捕獲:
@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()); } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Spring利用@Validated注解實(shí)現(xiàn)參數(shù)校驗(yàn)詳解
- Java中的三種校驗(yàn)注解的使用(@Valid,@Validated和@PathVariable)
- 使用注解@Validated和BindingResult對(duì)入?yún)⑦M(jìn)行非空校驗(yàn)方式
- SpringBoot @Validated注解實(shí)現(xiàn)參數(shù)分組校驗(yàn)的方法實(shí)例
- spring @Validated 注解開發(fā)中使用group分組校驗(yàn)的實(shí)現(xiàn)
- 使用@Validated注解進(jìn)行校驗(yàn)卻沒有效果的解決
相關(guān)文章
Java 中一個(gè)類提供一個(gè)默認(rèn)對(duì)象的多種方法
這篇文章主要介紹了Java 中一個(gè)類提供一個(gè)默認(rèn)對(duì)象的多種方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Java通過python命令執(zhí)行DataX任務(wù)的實(shí)例
今天小編就為大家分享一篇Java通過python命令執(zhí)行DataX任務(wù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-08-08Java實(shí)現(xiàn)直接插入排序和折半插入排序算法示例
這篇文章主要介紹了Java實(shí)現(xiàn)直接插入排序和折半插入排序算法示例,文中對(duì)算法的思想和時(shí)間復(fù)雜度都有簡(jiǎn)單的講解,需要的朋友可以參考下2016-04-04Spring Boot連接超時(shí)導(dǎo)致502錯(cuò)誤的實(shí)戰(zhàn)案例
這篇文章主要給大家介紹了關(guān)于Spring Boot連接超時(shí)導(dǎo)致502錯(cuò)誤的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Java中LinkedHashSet、LinkedHashMap源碼詳解
這篇文章主要介紹了Java中LinkedHashSet、LinkedHashMap源碼詳解,LinkedHashMap是一個(gè)以雙向鏈表的方式將Entry節(jié)點(diǎn)鏈接起來的HashMap子類,它在HashMap的基礎(chǔ)上實(shí)現(xiàn)了更多的功能,具有順序存儲(chǔ)和遍歷的特性,需要的朋友可以參考下2023-09-09淺析Java中SimpleDateFormat為什么是線程不安全的
SimpleDateFormat是Java中用于日期時(shí)間格式化的一個(gè)類,它提供了對(duì)日期的解析和格式化能力,本文主要來和大家一起探討一下SimpleDateFormat為什么是線程不安全的,感興趣的可以了解下2024-02-02Java 實(shí)現(xiàn)常見的非對(duì)稱加密算法
這篇文章主要介紹了Java 實(shí)現(xiàn)常見的非對(duì)稱加密算法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-11-11