SpringBoot參數(shù)校驗(yàn):@Valid與@Validated使用詳解
一、案例(參數(shù)校驗(yàn)的必要性)
傳統(tǒng)方式(無注解)的缺點(diǎn):
// 需要手動校驗(yàn)每個字段,代碼冗余且易出錯
public String register(User user) {
// 手動校驗(yàn)每個字段
if (user.getEmail() == null || !isValidEmail(user.getEmail())) {
throw new IllegalArgumentException("郵箱格式錯誤");
}
if (user.getPassword().length() < 8) {
throw new IllegalArgumentException("密碼長度需≥8位");
}
// 校驗(yàn)邏輯與業(yè)務(wù)代碼耦合,難以復(fù)用
}問題總結(jié):
- 代碼冗余:相同校驗(yàn)邏輯重復(fù)編寫
- 維護(hù)困難:校驗(yàn)規(guī)則分散,修改成本高
- 可讀性差:業(yè)務(wù)邏輯被大量
if-else淹沒
注解方式的優(yōu)勢:
public class User {
@Email(message = "郵箱格式不合法") // 一行注解替代復(fù)雜校驗(yàn)
private String email;
@Size(min = 8, message = "密碼長度需≥8位")
private String password;
}
@PostMapping("/register")
public String register(@Valid @RequestBody User user) {
// 校驗(yàn)邏輯由框架自動處理
return "success";
}核心優(yōu)勢:
- 聲明式校驗(yàn):通過注解自動完成參數(shù)驗(yàn)證
- 代碼簡潔:減少冗余的
if-else判斷 - 統(tǒng)一規(guī)范:標(biāo)準(zhǔn)化校驗(yàn)規(guī)則,降低維護(hù)成本
二、@Valid 注解
簡介
- Java標(biāo)準(zhǔn)注解(javax.validation)
- 用于觸發(fā) Bean Validation 校驗(yàn)機(jī)制
- 可校驗(yàn)方法參數(shù)和成員屬性
SpringBoot配置
<!-- pom.xml 必須依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>使用示例
public class User {
@NotNull(message = "用戶名不能為空")
private String name;
@Min(value = 18, message = "年齡必須≥18歲")
private Integer age;
}
@PostMapping("/users")
public String createUser(@Valid @RequestBody User user) { // 觸發(fā)校驗(yàn)
return "success";
}全局異常處理(核心實(shí)踐)
@RestControllerAdvice
public class GlobalExceptionHandler {
// 處理@Valid/@Validated拋出的校驗(yàn)異常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationException(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
}效果:自動返回結(jié)構(gòu)化錯誤信息(字段名+錯誤描述)
三、@Validated 注解
簡介
- Spring框架注解(org.springframework.validation.annotation)(@Validated是Spring框架提供的,導(dǎo)入springboot的依賴就會自動導(dǎo)入這個依賴)
- 支持分組校驗(yàn)(Group Validation)
- 可標(biāo)注在類、方法、參數(shù)上
核心功能
// 分組接口定義
public interface CreateGroup {}
public interface UpdateGroup {}
public class User {
@NotBlank(groups = CreateGroup.class)
private String name;
@NotNull(groups = {CreateGroup.class, UpdateGroup.class})
private Integer age;
}
// 使用分組校驗(yàn)
@PostMapping("/users")
public String createUser(@Validated(CreateGroup.class) @RequestBody User user) {
return "success";
}四、常用校驗(yàn)注解
最常用的注解:
| 注解 | 說明 | 示例 |
|---|---|---|
| @NotNull | 值不能為null | @NotNull(message="字段必填") |
| @NotBlank | 字符串非空(trim后) | 適用于用戶名、密碼等 |
| @Min/@Max | 數(shù)值范圍限制 | @Min(18) |
| @Pattern | 正則表達(dá)式校驗(yàn) | @Pattern(regexp="^1[3-9]\\d{9}$") |
| @Valid | 嵌套對象校驗(yàn) | 用于對象內(nèi)的子對象屬性 |
比較常用的注解:
| 注解 | 適用類型 | 說明 | 示例 |
|---|---|---|---|
| @Future | Date | 日期必須在未來 | @Future(message="截止時間無效") |
| @Digits | 數(shù)值類型 | 整數(shù)位和小數(shù)位限制 | @Digits(integer=3, fraction=2) |
| @Negative | 數(shù)值類型 | 必須為負(fù)數(shù) | 常用于財(cái)務(wù)系統(tǒng) |
| @NotEmpty | 集合/字符串 | 集合非空或字符串長度>0 | 比@NotBlank更寬松 |
組合注解(自定義)
// 自定義手機(jī)號校驗(yàn)注解
@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Phone {
String message() default "手機(jī)號格式不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 校驗(yàn)邏輯實(shí)現(xiàn)
public class PhoneValidator implements ConstraintValidator<Phone, String> {
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && PHONE_PATTERN.matcher(value).matches();
}
}使用場景:復(fù)用企業(yè)特定校驗(yàn)規(guī)則(如公司內(nèi)部員工編號)
五、@Valid 與 @Validated 區(qū)別
| 特性 | @Valid | @Validated |
|---|---|---|
| 標(biāo)準(zhǔn)規(guī)范 | JSR-303/JSR-349 標(biāo)準(zhǔn) | Spring 框架擴(kuò)展 |
| 分組校驗(yàn) | 不支持 | 支持 |
| 嵌套校驗(yàn) | 需要顯式添加@Valid | 不自動支持嵌套校驗(yàn) |
| 作用位置 | 方法參數(shù)、成員屬性 | 類、方法、參數(shù) |
六、高頻問題與最佳實(shí)踐
常見問題排查
注解不生效:
- 檢查是否忘記添加
@Valid/@Validated - 確保校驗(yàn)對象未被
@RequestBody等注解錯誤包裹
嵌套校驗(yàn)失敗:
- 確認(rèn)在嵌套對象屬性上添加了
@Valid
性能優(yōu)化建議
- 避免過度校驗(yàn):在Controller層做基礎(chǔ)校驗(yàn),復(fù)雜邏輯放到Service層
- 使用分組校驗(yàn):減少不必要的校驗(yàn)開銷
高級技巧
// 動態(tài)分組校驗(yàn)(根據(jù)請求參數(shù)決定校驗(yàn)組)
@Validated
@RestController
public class UserController {
@PostMapping("/users")
public String createUser(
@RequestParam String type,
@Validated({Default.class, type.equals("vip") ? VipGroup.class : Default.class})
@RequestBody User user
) {
return "success";
}
}實(shí)現(xiàn)原理:利用Spring EL表達(dá)式動態(tài)選擇校驗(yàn)組
七、重點(diǎn)總結(jié)
優(yōu)先使用場景:
- 優(yōu)先使用
@Valid的場景:嵌套對象校驗(yàn)、與非Spring框架整合 - 優(yōu)先使用
@Validated的場景:需要分組校驗(yàn)、校驗(yàn)Service層方法參數(shù)
配置要點(diǎn):
- 要想使用
@Valid必須添加spring-boot-starter-validation依賴 - 校驗(yàn)失敗會拋出
MethodArgumentNotValidException
最佳實(shí)踐:
// 嵌套校驗(yàn)示例
public class Order {
@Valid // 必須顯式添加
private User user;
}
// 分組校驗(yàn)示例
@Validated(UpdateGroup.class)
public void updateUser(@RequestBody User user) {}校驗(yàn)流程:
請求參數(shù) → 注解聲明 → 自動校驗(yàn) → 異常處理(@ControllerAdvice)
相較傳統(tǒng)參數(shù)校驗(yàn)優(yōu)勢:
- 減少70%以上的參數(shù)校驗(yàn)代碼量
- 通過統(tǒng)一異常處理實(shí)現(xiàn)錯誤響應(yīng)的標(biāo)準(zhǔn)化
- 提升代碼可維護(hù)性和團(tuán)隊(duì)協(xié)作效率
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
- SpringBoot集成Aviator實(shí)現(xiàn)參數(shù)校驗(yàn)的示例代碼
- Springboot項(xiàng)目參數(shù)校驗(yàn)方式(Validator)
- SpringBoot參數(shù)校驗(yàn)之@Valid與@Validated的用法與場景
- SpringBoot如何實(shí)現(xiàn)各種參數(shù)校驗(yàn)
- SpringBoot之controller參數(shù)校驗(yàn)詳解
- SpringBoot參數(shù)校驗(yàn)及原理全面解析
- SpringBoot參數(shù)校驗(yàn)的一些實(shí)戰(zhàn)應(yīng)用
相關(guān)文章
vue?vxe-table?實(shí)現(xiàn)財(cái)務(wù)記賬憑證的方案
使用?vxe-table?實(shí)現(xiàn)財(cái)務(wù)記賬憑證非常簡單,實(shí)現(xiàn)在線實(shí)時編輯的記賬憑證、自動合計(jì)金額等,這篇文章主要介紹了vue?vxe-table?實(shí)現(xiàn)財(cái)務(wù)記賬憑證的方案,需要的朋友可以參考下2024-12-12
利用Java異常機(jī)制實(shí)現(xiàn)模擬借書系統(tǒng)
這篇文章主要給大家介紹了利用Java異常機(jī)制實(shí)現(xiàn)模擬借書系統(tǒng)的相關(guān)資料,文中先對java異常機(jī)制進(jìn)行了簡單介紹,而后通過示例代碼介紹了java語言是如何實(shí)現(xiàn)一個控制臺版的模擬借書系統(tǒng),需要的朋友可以參考學(xué)習(xí),一起來看看吧。2017-04-04
Java創(chuàng)建對象的六種常用方式總結(jié)
作為Java開發(fā)者,經(jīng)常創(chuàng)建很多對象,你是否知道Java中創(chuàng)建對象有哪些方式呢?下面這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建對象的六種常用方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06
Java關(guān)鍵字finally_動力節(jié)點(diǎn)Java學(xué)院整理
java關(guān)鍵字finally不管是否出現(xiàn)異常,finally子句總是在塊完成之前執(zhí)行。下面通過實(shí)現(xiàn)代碼給大家介紹Java關(guān)鍵字finally相關(guān)知識,需要的的朋友參考下吧2017-04-04

