Spring中的@Valid 和 @Validated註解你用對了嗎
- 2021 年 1 月 14 日
- 筆記
- JAVA, java編程, Spring Boot
1.概述
本文我們將重點介紹Spring中 @Valid和@Validated註解的區別 。
驗證用戶輸入是否正確是我們應用程序中的常見功能。Spring提供了@Valid
和@Validated
兩個註解來實現驗證功能,下面我們來詳細介紹它們。
2. @Valid和@Validate註解
在Spring中,我們使用@Valid
註解進行方法級別驗證,同時還能用它來標記成員屬性以進行驗證。
但是,此注釋不支持分組驗證。@Validated
則支持分組驗證。
3.例子
讓我們考慮一個使用Spring Boot開發的簡單用戶註冊表單。首先,我們只有名稱
和密碼
屬性:
public class UserAccount {
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
// standard constructors / setters / getters / toString
}
接下來,讓我們看一下控制器。在這裡,我們將使用帶有@Valid
批註的saveBasicInfo
方法來驗證用戶輸入:
@RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
public String saveBasicInfo(
@Valid @ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result,
ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
現在讓我們測試一下這個方法:
@Test
public void givenSaveBasicInfo_whenCorrectInput`thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfo")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
在確認測試成功運行之後,現在讓我們擴展功能。下一步的邏輯步驟是將其轉換為多步驟註冊表格,就像大多數嚮導一樣。第一步,名稱
和密碼
保持不變。在第二步中,我們將獲取其他信息,例如age
和 phone
。因此,我們將使用以下其他字段更新域對象:
public class UserAccount {
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
@Min(value = 18, message = "Age should not be less than 18")
private int age;
@NotBlank
private String phone;
// standard constructors / setters / getters / toString
}
但是,這一次,我們將注意到先前的測試失敗。這是因為我們沒有傳遞年齡
和電話
字段。
為了支持此行為,我們引入支持分組驗證的@Validated
批註。
分組驗證
,就是將字段分組,分別驗證,比如我們將用戶信息分為兩組:BasicInfo
和AdvanceInfo
可以建立兩個空接口:
public interface BasicInfo {
}
public interface AdvanceInfo {
}
第一步將具有BasicInfo
接口,第二步 將具有AdvanceInfo
。此外,我們將更新UserAccount
類以使用這些標記接口,如下所示:
public class UserAccount {
@NotNull(groups = BasicInfo.class)
@Size(min = 4, max = 15, groups = BasicInfo.class)
private String password;
@NotBlank(groups = BasicInfo.class)
private String name;
@Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
private int age;
@NotBlank(groups = AdvanceInfo.class)
private String phone;
// standard constructors / setters / getters / toString
}
另外,我們現在將更新控制器以使用@Validated
注釋而不是@Valid
:
@RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
public String saveBasicInfoStep1(
@Validated(BasicInfo.class)
@ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
更新後,再次執行測試,現在可以成功運行。現在,我們還要測試這個新方法:
@Test
public void givenSaveBasicInfoStep1`whenCorrectInput`thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
也成功運行!
接下來,讓我們看看@Valid
對於觸發嵌套屬性驗證是必不可少的。
4.使用@Valid
批註標記嵌套對象
@Valid 可以用於嵌套對象。例如,在我們當前的場景中,讓我們創建一個 UserAddress
對象:
public class UserAddress {
@NotBlank
private String countryCode;
// standard constructors / setters / getters / toString
}
為了確保驗證此嵌套對象,我們將使用@Valid
批註裝飾屬性:
public class UserAccount {
//...
@Valid
@NotNull(groups = AdvanceInfo.class)
private UserAddress useraddress;
// standard constructors / setters / getters / toString
}
5. 總結
@Valid
保證了整個對象的驗證, 但是它是對整個對象進行驗證,當僅需要部分驗證的時候就會出現問題。 這時候,可以使用@Validated
進行分組驗證。
參考
作者:Jadepeng
出處:jqpeng的技術記事本–//www.cnblogs.com/xiaoqi
您的支持是對博主最大的鼓勵,感謝您的認真閱讀。
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。