在 Spring Boot 中,@Validated 是用于觸發參數校驗的注解,通常與 ??JSR-303/JSR-380??(Bean Validation)提供的校驗注解一起使用。以下是常見的校驗注解及其用法:
?1. 基本校驗注解??
這些注解可以直接用于字段、方法參數或方法返回值,結合 @Validated 進行校驗。
注解 | 作用 | 示例 |
---|---|---|
@NotNull | 不能為 null | @NotNull(message = “用戶名不能為空”) |
@NotEmpty | 不能為 null 且不能為空(適用于 String、Collection、Map、Array) | @NotEmpty(message = “列表不能為空”) |
@NotBlank | 不能為 null 且 trim() 后長度 > 0(僅適用于 String) | @NotBlank(message = “姓名不能為空”) |
@Null | 必須為 null | @Null(message = “ID 不能存在”) |
@AssertTrue | 必須為 true | @AssertTrue(message = “必須同意協議”) |
@AssertFalse | 必須為 false | @AssertFalse(message = “不能啟用”) |
@Past | 必須是過去的時間(Date、LocalDateTime 等) | @Past(message = “出生日期必須是過去”) |
@Future | 必須是未來的時間 | @Future(message = “截止時間必須是未來”) |
@Pattern(regex) | 必須匹配正則表達式 | @Pattern(regexp = "^[a-zA-Z0-9]+$", message = "只能包含字母和數字") |
@Size(min, max) | 字符串/集合/數組的長度范圍 | @Size(min = 2, max = 10, message = “長度必須在 2-10 之間”) |
@Length(min, max) | (Hibernate Validator 擴展)同 @Size | @Length(min = 2, max = 10) |
@Min(value) | 最小值(適用于 Number) | @Min(1, message = “年齡不能小于 1”) |
@Max(value) | 最大值(適用于 Number) | @Max(120, message = “年齡不能超過 120”) |
@DecimalMin(value) | 最小值(適用于 BigDecimal) | @DecimalMin(“0.01”, message = “金額不能小于 0.01”) |
@DecimalMax(value) | 最大值(適用于 BigDecimal) | @DecimalMax(“999999.99”) |
@Digits(integer, fraction) | 數字精度(整數位和小數位) | @Digits(integer = 5, fraction = 2, message = “最多 5 位整數,2 位小數”) |
必須是有效的郵箱格式 | @Email(message = “郵箱格式不正確”) |
??2. 分組校驗(groups)??
可以定義不同的校驗規則,并在特定場景下使用:
public class User {@NotNull(groups = {Create.class, Update.class}, message = "ID 不能為空")@Null(groups = {Delete.class}, message = "刪除時不能傳 ID")private Long id;@NotBlank(groups = Create.class, message = "創建時用戶名不能為空")private String username;public interface Create {}public interface Update {}public interface Delete {}
}
??Controller 使用分組校驗??:
@PostMapping("/create")
public String create(@Validated(User.Create.class) @RequestBody User user) {// 只校驗 Create 分組的規則return "Created";
}@PutMapping("/update")
public String update(@Validated(User.Update.class) @RequestBody User user) {// 只校驗 Update 分組的規則return "Updated";
}
??3. 嵌套對象校驗(@Valid)??
如果對象包含嵌套對象,需要用 @Valid 觸發嵌套校驗:
public class Order {@NotNullprivate Long id;@Valid // 觸發嵌套校驗@NotNullprivate User user; // User 類也需要校驗注解
}
??Controller 使用??:
@PostMapping("/order")
public String createOrder(@Validated @RequestBody Order order) {// 會校驗 Order 和 User 的所有校驗規則return "Order created";
}
??4. 自定義校驗注解??
如果內置注解不滿足需求,可以自定義校驗注解:
??示例:校驗 Integer 是否是 0 或 1??
1. 定義注解 @OneOrZero??
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = OneOrZeroValidator.class)
public @interface OneOrZero {String message() default "值必須是 0 或 1";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
2. 實現校驗邏輯 OneOrZeroValidator??
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;public class OneOrZeroValidator implements ConstraintValidator<OneOrZero, Integer> {@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return value == null || (value == 0 || value == 1);}
}
??3. 在實體類中使用??
public class MyRequest {@OneOrZero(message = "狀態必須是 0 或 1")private Integer status;
}
??5. 全局異常處理(@ControllerAdvice)??
當校驗失敗時,Spring 會拋出 MethodArgumentNotValidException,可以通過 @ControllerAdvice 統一處理:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;
import java.util.Map;@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {Map<String, String> errors = new HashMap<>();ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);}
}
??返回示例??:
{"username": "用戶名不能為空","email": "郵箱格式不正確"
}
??6. 常見問題??
??Q1: @Valid 和 @Validated 的區別???
注解 | 作用 | 適用場景 |
---|---|---|
@Valid | 觸發 JSR-303 校驗 | 一般用于嵌套對象校驗(如 @Valid User user) |
@Validated | Spring 提供的增強版,支持分組校驗 | 一般用于 Controller 方法參數校驗 |
??Q2: 為什么 @Validated 不生效???
- 檢查是否在 ??Controller 類或方法參數?? 上使用了 @Validated。
- 確保依賴正確(Spring Boot 默認包含 spring-boot-starter-validation)。
- 如果校驗的是 List 或 Map,確保使用 @Valid 嵌套校驗:
public class Request {@Valid // 必須加 @Validprivate List<User> users;}
7. ??總結??
場景 | 推薦注解 |
---|---|
基本校驗 | @NotNull, @NotEmpty, @Pattern, @Size |
分組校驗 | groups + @Validated |
嵌套校驗 | @Valid |
自定義校驗 | @Constraint + ConstraintValidator |
全局異常處理 | @ControllerAdvice |
通過合理使用這些注解,可以輕松實現參數校驗,提高代碼健壯性! 🚀