參數(shù)校驗(yàn)Spring的@Valid注解用法解析
參數(shù)校驗(yàn)Spring的@Valid注解
@Valid 注解通常用于對(duì)象屬性字段的規(guī)則檢測(cè)。
以新增一個(gè)員工為功能切入點(diǎn),以常規(guī)寫(xiě)法為背景,慢慢烘托出 @Valid 注解用法詳解。
那么,首先,我們會(huì)有一個(gè)員工對(duì)象 Employee,如下 :
public class Employee { /** 姓名 */ public String name; /** 年齡 */ public Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
然后 Cotroller 中會(huì)有一個(gè)對(duì)應(yīng)都新增方法 add():
@Controller public class TestController { @RequestMapping("/add") @ResponseBody public String add(Employee employee) { // TODO 保存到數(shù)據(jù)庫(kù) return "新增員工成功"; } }
需求變更,要求員工名稱不能為空,且長(zhǎng)度不超過(guò)10個(gè)字符
我們的原始寫(xiě)法:
現(xiàn)在規(guī)定年齡也是必填項(xiàng),且范圍在1到100歲,那么此時(shí),我們需要增加判定
現(xiàn)在員工對(duì)象 Employee 就 2 個(gè)字段,我們就寫(xiě)了 10 多行的代碼驗(yàn)證,要是有20個(gè)字段,豈不是要寫(xiě) 100 多行代碼?
如何解決呢?
將驗(yàn)證過(guò)程抽成一個(gè)驗(yàn)證方法:
但這種方式只是抽了一個(gè)方法,有一種換湯不換藥的感覺(jué),雖然業(yè)務(wù)方法看起來(lái)清爽了很多,但書(shū)寫(xiě)代碼量并沒(méi)有下降,反而還多出了一個(gè)方法。
此時(shí)引出 Spring 的 @valid 注解即可:
首先,我們?cè)?Maven 配置中引入 @valid 的依賴:
如果你是 springboot 項(xiàng)目,那么可以不用引入了,已經(jīng)引入了,他就存在于最核心的 web 開(kāi)發(fā)包里面。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.0.5.RELEASE</version> </dependency>
代碼優(yōu)化
首先在 Employee 類的屬性上打上如下注解:
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Range; public class Employee { /** 姓名 */ @NotBlank(message = "請(qǐng)輸入名稱") @Length(message = "名稱不能超過(guò)個(gè) {max} 字符", max = 10) public String name; /** 年齡 */ @NotNull(message = "請(qǐng)輸入年齡") @Range(message = "年齡范圍為 {min} 到 {max} 之間", min = 1, max = 100) public Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
然后再 Controller 對(duì)應(yīng)方法上,對(duì)這個(gè)員工標(biāo)上 @Valid 注解,表示我們對(duì)這個(gè)對(duì)象屬性需要進(jìn)行驗(yàn)證
用一個(gè)東西來(lái)存放驗(yàn)證結(jié)果,做法也很簡(jiǎn)單,在參數(shù)直接添加一個(gè)BindingResult:
對(duì)應(yīng)獲取驗(yàn)證結(jié)果的代碼如下:
@Valid與@Validated注解
之前項(xiàng)目中參數(shù)的校驗(yàn),都是自己寫(xiě)的判斷方法進(jìn)行校驗(yàn),這次采用了spring提供的注解進(jìn)行參數(shù)的校驗(yàn),更為的方便,簡(jiǎn)潔。
@Valid:常見(jiàn)用在方法,類中字段上進(jìn)行校驗(yàn)
@Validated:是spring提供的對(duì)@Valid的封裝,常見(jiàn)用在方法上進(jìn)行校驗(yàn)
定義的校驗(yàn)類型
@Null
驗(yàn)證對(duì)象是否為null
@NotNull
驗(yàn)證對(duì)象是否不為null, 無(wú)法查檢長(zhǎng)度為0的字符串
@NotBlank
檢查約束字符串是不是Null還有被Trim的長(zhǎng)度是否大于0,只對(duì)字符串,且會(huì)去掉前后空格.
@NotEmpty
檢查約束元素是否為NULL或者是EMPTY.
@CreditCardNumber
信用卡驗(yàn)證
@Email
驗(yàn)證是否是郵件地址,如果為null,不進(jìn)行驗(yàn)證,算通過(guò)驗(yàn)證。
@URL
(protocol=,host=, port=,regexp=, flags=) ip地址校驗(yàn)
Booelan檢查
@AssertTrue
驗(yàn)證 Boolean 對(duì)象是否為 true
@AssertFalse
驗(yàn)證 Boolean 對(duì)象是否為 false
長(zhǎng)度檢查
@Size(min=, max=)
驗(yàn)證對(duì)象(Array,Collection,Map,String)長(zhǎng)度是否在給定的范圍之內(nèi)
@Length(min=, max=) Validates that the annotated string is between min and max included.
日期檢查
@Past
驗(yàn)證 Date 和 Calendar 對(duì)象是否在當(dāng)前時(shí)間之前
@Future
驗(yàn)證 Date 和 Calendar 對(duì)象是否在當(dāng)前時(shí)間之后
@Pattern
驗(yàn)證 String 對(duì)象是否符合正則表達(dá)式的規(guī)則
數(shù)值檢查,建議使用在Stirng,Integer類型,不建議使用在int類型上,因?yàn)楸韱沃禐?"時(shí)無(wú)法轉(zhuǎn)換為int,但可以轉(zhuǎn)換為Stirng為"",Integer為null
@Min
驗(yàn)證 Number 和 String 對(duì)象是否大等于指定的值
@Max
驗(yàn)證 Number 和 String 對(duì)象是否小等于指定的值
@DecimalMax
被標(biāo)注的值必須不大于約束中指定的最大值. 這個(gè)約束的參數(shù)是一個(gè)通過(guò)BigDecimal定義的最大值的字符串表示.小數(shù)存在精度
@DecimalMin 被標(biāo)注的值必須不小于約束中指定的最小值. 這個(gè)約束的參數(shù)是一個(gè)通過(guò)BigDecimal定義的最小值的字符串表示.小數(shù)存在精度
@Digits
驗(yàn)證 Number 和 String 的構(gòu)成是否合法
@Digits(integer=,fraction=)
驗(yàn)證字符串是否是符合指定格式的數(shù)字,interger指定整數(shù)精度,fraction指定小數(shù)精度。
@Range(min=, max=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum.
注意的幾點(diǎn):
(1)如果一個(gè)bean中包含第二個(gè)bean
這時(shí)要檢驗(yàn)第二個(gè)bean中某個(gè)字段,即嵌套校驗(yàn),必須要在第一個(gè)bean對(duì)象中使用@Valid標(biāo)注到表示第二個(gè)bean對(duì)象的字段上,然后再第二個(gè)bean對(duì)象里面的字段上加上校驗(yàn)類型
(2)@Validated支持分組注解
1、先定義一個(gè)空接口:GroupA
2、對(duì)bean對(duì)象中校驗(yàn)類型,添加分組信息,這里我對(duì)version字段進(jìn)行了分組校驗(yàn)信息添加
3、方法入?yún)⒅羞M(jìn)行分組信息添加
如上圖所示,則shelveProject方法由于添加了分組信息會(huì)校驗(yàn)DeleteProjectRequest對(duì)象中的version字段是否為空,而offShelveProject方法沒(méi)有添加分組信息,不會(huì)校驗(yàn)version是否為空。
@Validated沒(méi)有添加groups屬性時(shí),默認(rèn)驗(yàn)證沒(méi)有分組的驗(yàn)證屬性。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC中請(qǐng)求參數(shù)的獲取方式
這篇文章主要為大家介紹了SpringMVC中請(qǐng)求參數(shù)的獲取方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05java.lang.NullPointerException出現(xiàn)的幾種原因及解決方案
這篇文章主要介紹了java.lang.NullPointerException出現(xiàn)的幾種原因及解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05java WebSocket客戶端斷線重連的實(shí)現(xiàn)方法
在工作中是否會(huì)遇到實(shí)用websocket客戶端連接服務(wù)端的時(shí)候,網(wǎng)絡(luò)波動(dòng),服務(wù)端斷連的情況,本文可以直接使用的斷線重連,感興趣的可以了解一下2021-10-10java連接Oracle數(shù)據(jù)庫(kù)的工具類
這篇文章主要介紹了java連接Oracle數(shù)據(jù)庫(kù)的工具類,非常的實(shí)用,需要的小伙伴參考下。2015-03-03解讀nextLine().split(“[\\s]“)的意思
這篇文章主要介紹了解讀nextLine().split(“[\\s]“)的意思,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04