通過?@Validated
?和?@Valid可以對請求的進行參數校驗。
1.核心對比:
特性 | @Valid ?(JSR-303) | @Validated ?(Spring) |
---|---|---|
來源 | Java標準規范 | Spring框架擴展 |
分組校驗 | 不支持 | 支持(通過groups 屬性) |
嵌套路徑 | 自動處理級聯校驗 | 需配合@Valid 生效 |
應用范圍 | 方法參數、屬性、返回值 | 類、方法、參數 |
List校驗 | 需放在集合聲明處 | 需配合@Valid 生效 |
2.基礎使用示例
?2.1 單對象校驗
public class UserDTO {@NotBlank(message = "用戶名不能為空")private String username;@Email(message = "郵箱格式錯誤")private String email;
}// 使用@Valid
@PostMapping("/users")
public Result createUser(@RequestBody @Valid UserDTO user) {// ...
}// 使用@Validated
@RestController
@Validated // 類級別啟用校驗
public class UserController {@PostMapping("/users")public Result createUser(@RequestBody @Validated UserDTO user) {// ...}
}
3. 級聯屬性校驗
3.1 嵌套對象校驗
public class OrderDTO {@NotNullprivate Long orderId;@Valid // 關鍵注解,啟用嵌套校驗private UserDTO user;
}// 測試
@PostMapping("/orders")
public Result createOrder(@RequestBody @Valid OrderDTO order) {// 會自動校驗order.user里的約束
}
3.2 集合元素校驗
public class BatchRequest {@Size(min = 1, max = 10)private List<@Valid UserDTO> users; // 校驗每個元素
}@PostMapping("/batch")
public Result batchCreate(@RequestBody @Valid BatchRequest request) {// 會校驗list內每個UserDTO
}
4. 分組校驗(僅@Validated支持)
4.1 定義校驗分組
public interface CreateCheck {}
public interface UpdateCheck {}public class ProductDTO {@Null(groups = CreateCheck.class) // 創建時ID必須為空@NotNull(groups = UpdateCheck.class) // 更新時ID不能為空private Long id;@NotBlank(groups = {CreateCheck.class, UpdateCheck.class})private String name;
}
4.2 使用分組
@PostMapping("/products")
public Result create(@RequestBody @Validated(CreateCheck.class) ProductDTO product) {// 僅觸發CreateCheck組的校驗
}@PutMapping("/products/{id}")
public Result update(@PathVariable Long id, @RequestBody @Validated(UpdateCheck.class) ProductDTO product) {// 僅觸發UpdateCheck組的校驗
}
5.統一異常處理
@RestControllerAdvice
public class GlobalExceptionHandler {// 處理@Validated和@Valid拋出的異常@ExceptionHandler(MethodArgumentNotValidException.class)public Result handleValidException(MethodArgumentNotValidException e) {List<String> errors = e.getBindingResult().getFieldErrors().stream().map(error -> error.getField() + ": " + error.getDefaultMessage()).collect(Collectors.toList());return Result.fail(400, "參數錯誤", errors);}
}
6.最佳實現
6.1 混合使用
類/方法級用 @Validated參數/屬性級用 @Valid
6.2 性能優化
// 避免在循環中校驗
@Validated
@Service
public class UserService {public void batchProcess(@Valid List<UserDTO> users) {// 批量處理}
}
6.3 自定義校驗
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {String message() default "手機號格式錯誤";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
6.4 復雜場景
// 級聯校驗+集合校驗
public class DepartmentDTO {@Validprivate List<@Valid EmployeeDTO> employees;@Validprivate AddressDTO location;
}