有這么一個場景,假設前台傳遞給我們三個參數 id、name、age ,我們很自然的會想到使用 @RequestParam 來接收前台傳遞過來的參數,具體示例如下
@GetMapping("/getUserInfo")
public String getUserInfo(
// 將前台傳遞過來的參數 id 對應的值綁定至 Integer 類型的參數 id
// required 的默認值是 true,如果前台傳遞過來沒有該參數,那么就會進行校驗並報錯
// 當 required = false 時,如果沒有傳遞參數 id,那么它不會報錯,而是使用默認值 10086
@RequestParam(value="id",required = false,defaultValue = "10086") Integer id,
@RequestParam(value="name",required = false,defaultValue = "xiaomaomao") String name,
@RequestParam(value = "age",required = false,defaultValue = "21") Integer age) {
return "id===" + id + " name===" + name + " age===" + age;
}
上面的示例看起來沒有什么問題,可是實際上我們不難發現,如果前台傳遞過來的參數不是三個,而是十個,如果繼續使用 @RequestParam 的方式來接收請求參數,就需要十個 @RequestParam ,我們的代碼可讀性將會變得很差,並且當參數類型相同時,十分容易出錯,有沒有什么好的解決方案呢?
這個時候可能你會想到使用實體類來接收傳遞過來的十個參數,想法是正確的,可是 @RequestParam 不支持直接傳遞實體類的方式,那么有其它的解決辦法嗎?
答案是有的,具體示例如下
@GetMapping("/getUserInfo")
// 將請求參數中的 id、name、age 與實體類 saleman 進行綁定
public String getUserInfo(Saleman saleman) {
return saleman.toString();
}
很簡單,只需要定義一個實體類就能完美解決,可是,如果要實現類似於 @RequestParam(required=true) 的校驗該怎么辦呢?
其實也好辦,我們可以在實體類里面進行校驗
@Data
public class Saleman {
// id 最小值為 100
@Min(1)
// id 不能為空,否則會報錯
@NonNull
private Integer id;
// 如果是字符串類型的數據,使用 @NotBlank 比 @NoNull 更好,因為 @NotBlank 不僅會校驗 null 值,它還會校驗空字符串
@NotBlank
private String name;
// age 最大值為 30
@Max(30)
// age 不能為空,否則校驗不通過
@NonNull
private Integer age;
}
注意你如果想要這些實體類中的注解生效,就必須要加上 @Valid 注解
@GetMapping("/getUserInfo")
// 要想實體類中的注解生效,必須要在實體類加上 @Valid 注解
public String getUserInfo(@Valid Saleman saleman) {
return saleman.toString();
}
這樣,我們就模擬出了 @RequestParam(required=true) 的情形了,但是 @RequestParam 注解的作用還包括,如果未提供具體的參數,它會有默認值,這個該怎么實現呢?
做法很簡單,只需要在聲明實體類屬性的時候給一個默認值即可,類似 private Integer id = 2
@Data
public class Saleman {
// id 最小值為 100
@Min(1)
// id 不能為空,否則會報錯
@NonNull
// 如果前台沒有傳遞 id 參數,那么 id 會有默認值 2,注意這里的默認值一定要符合上面 @Min、@Nonnull 等注解的校驗,否則該默認值設置的是不合理的
private Integer id = 2;
// 如果是字符串類型的數據,使用 @NotBlank 比 @NoNull 更好,因為 @NotBlank 不僅會校驗 null 值,它還會校驗空字符串
@NotBlank
private String name = "xiaomaomi";
// age 最大值為 30
@Max(30)
// age 不能為空,否則校驗不通過
@NonNull
private Integer age = 28;
}
@GetMapping("/getUserInfo")
// 要想實體類中的注解生效,必須要在實體類加上 @Valid 注解
public String getUserInfo(@Valid Saleman saleman) {
return saleman.toString();
}
到此,我們就已經模擬出了 @RequestParam 注解的所有功能(空值校驗、空值時的默認值)
有時候根據業務需求,不會把所有的請求參數封裝進同一個實體類中,我們可以將其封裝進多個實體類中,具體的用法同上面一個實體類的相同
@Data
public class Saleman {
// id 最小值為 100
@Min(1)
// id 不能為空,否則會報錯
@NonNull
// 如果前台沒有傳遞 id 參數,那么 id 會有默認值 2,注意這里的默認值一定要符合上面 @Min、@Nonnull 等注解的校驗,否則該默認值設置的是不合理的
private Integer id = 2;
// 如果是字符串類型的數據,使用 @NotBlank 比 @NoNull 更好,因為 @NotBlank 不僅會校驗 null 值,它還會校驗空字符串
@NotBlank
private String name = "xiaomaomi";
// age 最大值為 30
@Max(30)
// age 不能為空,否則校驗不通過
@NonNull
private Integer age = 28;
}
@Data
public class Product {
@Min(100)
@NonNull
private Integer id = 10001;
@NotBlank
private String productName = "yishengwenhou";
}
@GetMapping("/getUserInfo")
// 要想實體類中的注解生效,必須要在實體類加上 @Valid 注解
public String getUserInfo(@Valid Saleman saleman,@Valid Product product) {
return saleman.toString() + "--------" + product.toString();
}
但是有一個需要注意的地方,如果兩個實體類中有相同的屬性,那么前台傳入的參數值會同時封裝進入兩個實體類中,例如前台傳入一個 id,而 Saleman、Product 兩個實體類都有 id 這個屬性,那么 id 對應的參數值就同時封裝進了 saleman、product