別再亂用了,這才是 @Validated 和 @Valid 的真正區(qū)別!!!
Hollis的新書(shū)限時(shí)折扣中,一本深入講解Java基礎(chǔ)的干貨筆記!
概述
@Valid是使用Hibernate validation的時(shí)候使用@Validated是只用Spring Validator校驗(yàn)機(jī)制使用
說(shuō)明:java的JSR303聲明了
@Valid這類(lèi)接口,而Hibernate-validator對(duì)其進(jìn)行了實(shí)現(xiàn)
@Validation對(duì)@Valid進(jìn)行了二次封裝,在使用上并沒(méi)有區(qū)別,但在分組、注解位置、嵌套驗(yàn)證等功能上有所不同,這里主要就這幾種情況進(jìn)行說(shuō)明。
注解位置
@Validated:用在類(lèi)型、方法和方法參數(shù)上。但不能用于成員屬性(field)@Valid:可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(field)上
如:


如果@Validated注解在成員屬性上,則會(huì)報(bào)不適用于field錯(cuò)誤
分組校驗(yàn)
@Validated:提供分組功能,可以在參數(shù)驗(yàn)證時(shí),根據(jù)不同的分組采用不同的驗(yàn)證機(jī)制@Valid:沒(méi)有分組功能
舉例:
定義分組接口:
public?interface?IGroupA?{
}
?
public?interface?IGroupB?{
}
定義需要檢驗(yàn)的參數(shù)bean:
public?class?StudentBean?implements?Serializable{
????@NotBlank(message?=?"用戶(hù)名不能為空")
????private?String?name;
????//只在分組為IGroupB的情況下進(jìn)行驗(yàn)證
????@Min(value?=?18,?message?=?"年齡不能小于18歲",?groups?=?{IGroupB.class})
????private?Integer?age;
????@Pattern(regexp?=?"^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$",?message?=?"手機(jī)號(hào)格式錯(cuò)誤")
????private?String?phoneNum;
????@Email(message?=?"郵箱格式錯(cuò)誤")
????private?String?email;
????@MyConstraint
????private?String?className;
測(cè)試代碼:
檢驗(yàn)分組為IGroupA的情況
@RestController
public?class?CheckController?{
????@PostMapping("stu")
????public?String?addStu(@Validated({IGroupA.class})?@RequestBody?StudentBean?studentBean){
????????return?"add?student?success";
????}
}
測(cè)試:

這里對(duì)分組IGroupB的就沒(méi)檢驗(yàn)了
如果把測(cè)試代碼改成下面這樣,看看測(cè)試結(jié)果
@RestController
public?class?CheckController?{
????@PostMapping("stu")
????public?String?addStu(@Validated({IGroupA.class,?IGroupB.class})?@RequestBody?StudentBean?studentBean){
????????return?"add?student?success";
????}
}
說(shuō)明:
1、不分 配groups,默認(rèn)每次都要進(jìn)行驗(yàn)證
2、對(duì)一個(gè)參數(shù)需要多種驗(yàn)證方式時(shí),也可通過(guò)分配不同的組達(dá)到目的。
組序列
默認(rèn)情況下 不同級(jí)別的約束驗(yàn)證是無(wú)序的,但是在一些情況下,順序驗(yàn)證卻是很重要。
一個(gè)組可以定義為其他組的序列,使用它進(jìn)行驗(yàn)證的時(shí)候必須符合該序列規(guī)定的順序。在使用組序列驗(yàn)證的時(shí)候,如果序列前邊的組驗(yàn)證失敗,則后面的組將不再給予驗(yàn)證。
舉例:
定義組序列:
@GroupSequence({Default.class,?IGroupA.class,?IGroupB.class})
public?interface?IGroup?{
}
需要校驗(yàn)的Bean,分別定義IGroupA對(duì)age進(jìn)行校驗(yàn),IGroupB對(duì)className進(jìn)行校驗(yàn):
public?class?StudentBean?implements?Serializable{
????@NotBlank(message?=?"用戶(hù)名不能為空")
????private?String?name;
????@Min(value?=?18,?message?=?"年齡不能小于18歲",?groups?=?IGroupA.class)
????private?Integer?age;
????@Pattern(regexp?=?"^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$",?message?=?"手機(jī)號(hào)格式錯(cuò)誤")
????private?String?phoneNum;
????@Email(message?=?"郵箱格式錯(cuò)誤")
????private?String?email;
????@MyConstraint(groups?=?IGroupB.class)
????private?String?className;
測(cè)試代碼:
@RestController
public?class?CheckController?{
????@PostMapping("stu")
????public?String?addStu(@Validated({IGroup.class})?@RequestBody?StudentBean?studentBean){
????????return?"add?student?success";
????}
}
測(cè)試發(fā)現(xiàn),如果age出錯(cuò),那么對(duì)組序列在IGroupA后的IGroupB不進(jìn)行校驗(yàn),即例子中的className不進(jìn)行校驗(yàn),結(jié)果如下:

嵌套校驗(yàn)
一個(gè)待驗(yàn)證的pojo類(lèi),其中還包含了待驗(yàn)證的對(duì)象,需要在待驗(yàn)證對(duì)象上注解@Valid,才能驗(yàn)證待驗(yàn)證對(duì)象中的成員屬性,這里不能使用@Validated。
舉例:
需要約束校驗(yàn)的bean:
public?class?TeacherBean?{
????@NotEmpty(message?=?"老師姓名不能為空")
????private?String?teacherName;
????@Min(value?=?1,?message?=?"學(xué)科類(lèi)型從1開(kāi)始計(jì)算")
????private?int?type;
public?class?StudentBean?implements?Serializable{
????@NotBlank(message?=?"用戶(hù)名不能為空")
????private?String?name;
????@Min(value?=?18,?message?=?"年齡不能小于18歲")
????private?Integer?age;
????@Pattern(regexp?=?"^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$",?message?=?"手機(jī)號(hào)格式錯(cuò)誤")
????private?String?phoneNum;
????@Email(message?=?"郵箱格式錯(cuò)誤")
????private?String?email;
????@MyConstraint
????private?String?className;
?
????@NotNull(message?=?"任課老師不能為空")
????@Size(min?=?1,?message?=?"至少有一個(gè)老師")
????private?List?teacherBeans;
注意:
這里對(duì)teacherBeans只校驗(yàn)了NotNull, 和 Size,并沒(méi)有對(duì)teacher信息里面的字段進(jìn)行校驗(yàn),具體測(cè)試如下:

這里teacher中的type明顯是不符合約束要求的,但是能檢測(cè)通過(guò),是因?yàn)樵趕tudent中并沒(méi)有做 嵌套校驗(yàn)
可以在teacherBeans中加上?@Valid,具體如下:
@Valid
@NotNull(message?=?"任課老師不能為空")
@Size(min?=?1,?message?=?"至少有一個(gè)老師")
private?List?teacherBeans;
這里再來(lái)測(cè)試,會(huì)發(fā)現(xiàn)如下結(jié)果:

來(lái)源:blog.csdn.net/herojuice/article/
details/86020101
完
我的新書(shū)《深入理解Java核心技術(shù)》已經(jīng)上市了,上市后一直蟬聯(lián)京東暢銷(xiāo)榜中,目前正在6折優(yōu)惠中,想要入手的朋友千萬(wàn)不要錯(cuò)過(guò)哦~長(zhǎng)按二維碼即可購(gòu)買(mǎi)~
長(zhǎng)按掃碼享受6折優(yōu)惠
往期推薦

有人冒充我,而且還在直播?

阿里、華為和微軟等多家國(guó)內(nèi)外廠商組團(tuán)搞OpenJDK,Oracle為啥不參加?

公司大裁員!我裁掉了那個(gè),最努力的員工
有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號(hào)
好文章,我在看??
