Spring註解之引數校驗@Validated和@Valid
詳解Spring 引數驗證@Validated和@Valid的區別
Spring Validation驗證框架對引數的驗證機制提供了@Validated(Spring's JSR-303 規範,是標準 JSR-303 的一個變種),javax提供了@Valid(標準JSR-303規範),配合 BindingResult 可以直接提供引數驗證結果。
在檢驗 Controller 的入參是否符合規範時,使用 @Validated 或者 @Valid 在基本驗證功能上沒有太多區別。
但是在分組、註解地方、巢狀驗證等功能上兩個有所不同:
1. 分組
@Validated:提供了一個分組功能,可以在入參驗證時,根據不同的分組採用不同的驗證機制,這個網上也有資料,不詳述。
@Valid:作為標準JSR-303規範,還沒有吸收分組的功能。
2. 註解地方
@Validated:可以用在型別、方法和方法引數上。但是不能用在成員屬性(欄位)上。
@Valid:可以用在建構函式、方法和方法引數和成員屬性(欄位)上。
兩者是否能用於成員屬性(欄位)上直接影響能否提供巢狀驗證的功能。
3. 巢狀驗證
在比較兩者巢狀驗證時,先說明下什麼叫做巢狀驗證。比如我們現在有個實體叫做Item:
public class Item { @NotNull(message = "id不能為空") @Min(value = 1, message = "id必須為正整數") private Long id; @Valid // 巢狀驗證必須用@Valid @NotNull(message = "props不能為空") @Size(min = 1, message = "至少要有一個屬性") private List<Prop> props; }
Item的成員屬性props必須加上@Valid註解支援巢狀驗證功能。
Item帶有很多屬性,如下所示:
public class Prop { @NotNull(message = "pid不能為空") @Min(value = 1, message = "pid必須為正整數") private Long pid; @NotNull(message = "vid不能為空") @Min(value = 1, message = "vid必須為正整數") private Long vid; @NotBlank(message = "pidName不能為空") private String pidName; @NotBlank(message = "vidName不能為空") private String vidName; }
屬性這個實體也有自己的驗證機制,比如屬性和屬性值id不能為空,屬性名和屬性值不能為空等。
現在我們有個 ItemController 接受一個Item的入參,想要對Item進行驗證,如下所示:
@RestController
public class ItemController {
@RequestMapping("/item/add")
public void addItem(@Validated Item item, BindingResult bindingResult) {
doSomething();
}
}
此時Item裡面的props如果含有Prop的相應欄位為空的情況,Spring Validation框架就會檢測出來,bindingResult就會記錄相應的錯誤。
@Validated分組校驗
定義實體類
@Data
public class User {
@NotBlank(groups = {UpdateGroup.class}, message = "id不能為空")
private String id;
@NotBlank(groups = {SaveGroup.class, UpdateGroup.class}, message = "姓名不能為空")
private String name;
@NotNull(message = "性別不能為空")
private String sex;
@Max(value = 20 ,message = "最大長度為20")
private String address;
@Email(message = "不滿足郵箱格式")
private String email;
@AssertTrue(message = "欄位為true才能通過")
private boolean isAuth;
@NotBlank(message = "手機號不能為空")
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤")
private String mobile;
@Future(message = "時間在當前時間之後才可以通過")
private Date date;
// 新增時校驗,繼承Default類表示會包含沒有分組的校驗
public interface SaveGroup extends Default {
}
// 修改時校驗
public interface UpdateGroup extends Default {
}
}
controller 介面中使用 @Validated(groups) 設定了 groups 屬性。
只有配置 groups = User.SaveGroup.class 的效驗註解才會生效。
沒有設定 groups 屬性,則所有效驗註解都會生效。
@RestController(value = "/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 新增使用者
* @param user
* @return
*/
@RequestMapping("/insert")
@ResponseBody
public User insert(@RequestBody @Validated(User.SaveGroup.class) User user){
return userService.insert(user);
}
/**
* 修改使用者
* @param user
* @return
*/
@RequestMapping("/update")
@ResponseBody
public boolean update(@RequestBody @Validated(User.UpdateGroup.class) User user){
return userService.update(user);
}
}
對Controller裡的方法的多個引數進行校驗
對Controller裡的方法的多個引數進行校驗(扁平化引數):在Controller類上加註解@Validated
@RestController
@RequestMapping
@Validated
public class HelloController {
@PutMapping("/hello/id/{id}/status/{status}")
public Object helloGet(@Max(5) @PathVariable Integer id, @Min(5) @PathVariable Integer status) {
return "hello world";
}
}
@NotEmpty、@NotNull、@NotBlank的區別
-
@NotNull :不能為null,但可以為empty,沒有Size的約束,帶註釋的元素不能為null。接受任何型別。一般用在Integer、Double等基本資料型別的非空校驗上,使用** @size、@Max、@Min **對欄位數值進行大小的控制。
-
@NotEmpty:不能為null,且Size>0,@NotEmpty註解的String、Collection、Map、陣列是不能為null或長度為0
-
@NotBlank:只用於String,不能為null且trim()之後size>0,純空格的String也是不符合規則的,此註解只能用於驗證String型別