Spring Boot 参数校验-@Valid、@Validated
📦 依赖引入
在 pom.xml
中添加以下依赖,启用 Bean Validation:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
🧠 核心注解说明
注解 | 说明 |
---|
@NotNull | 不为 null |
@NotEmpty | 不为 null 且不为空 |
@NotBlank | 不为 null 且去空格后不为空 |
@Min / @Max | 数值大小限制 |
@Email | 邮箱格式校验 |
@Pattern | 正则表达式校验 |
@Size | 长度或集合大小范围 |
@Valid | 启用嵌套对象校验 |
@Validated | 启用分组校验或方法级校验 |
✅ @Valid 和 @Validated 区别
特性 | @Valid | @ @Validated`` |
---|
所属包 | javax.validation.Valid | org.springframework.validation.annotation.Validated |
分组校验支持 | ❌ 不支持 | ✅ 支持 |
方法参数校验支持 | ❌ 不支持 | ✅ 支持 |
嵌套对象校验支持 | ✅ 支持 | ✅ 支持 |
用于类级方法参数校验 | ❌ 无效 | ✅ 有效 |
🚀 使用示例
1. 创建 DTO 对象
@Data
public class UserDTO {
@Size(min = 2, max = 5, message = "用户名长度必须在2~5之间")
private String username;
@Email(message = "邮箱格式错误")
private String email;
@Min(value = 18, message = "年龄必须 >= 18")
private Integer age;
}
2. Controller 使用校验
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/create")
public String createUser(@Valid @RequestBody UserDTO userDTO) {
return "用户创建成功";
}
}
3. 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidation(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(err ->
errors.put(err.getField(), err.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
}
🧩 分组校验示例
public class UserDTO {
public interface Create {}
public interface Update {}
@Null(groups = Create.class)
@NotNull(groups = Update.class)
private Long id;
@NotBlank(groups = {Create.class, Update.class})
private String username;
}
@PostMapping("/add")
public String add(@Validated(UserDTO.Create.class) @RequestBody UserDTO dto) {}
@PostMapping("/update")
public String update(@Validated(UserDTO.Update.class) @RequestBody UserDTO dto) {}
🛠 方法级参数校验
@Validated
@Service
public class UserService {
public void updateUser(@NotNull(message = "ID不能为空") Long id) {
}
}
✅ 总结
你想做什么 | 推荐使用 |
---|
基本请求体校验 | @Valid |
分组校验 | @Validated |
Controller / Service 方法参数校验 | 类上加 @Validated |
⚠️ 三种常见的参数校验异常说明
1. MethodArgumentNotValidException
- 出现场景:使用
@Valid @RequestBody
的 DTO 参数校验失败 - 常用于:JSON 请求体
- 处理方式:
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
String msg = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
return ResponseEntity.badRequest().body(msg);
}
2. ConstraintViolationException
- 出现场景:使用
@Validated
对 @RequestParam
/ 基础类型参数进行校验 - 常用于:方法入参、Query参数等
- 处理方式:
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handleConstraintViolation(ConstraintViolationException ex) {
String msg = ex.getConstraintViolations().iterator().next().getMessage();
return ResponseEntity.badRequest().body(msg);
}
3. HandlerMethodValidationException(Spring Boot 3 / Spring 6 及以上)
- 出现场景:方法级参数校验失败(Controller 或 Service)
- 说明:Spring 6 引入的统一校验异常,封装了多个底层校验异常
- 处理方式:
@ExceptionHandler(HandlerMethodValidationException.class)
public ResponseEntity<?> handleHandlerMethodValidation(HandlerMethodValidationException ex) {
String msg = ex.getAllValidationResults().get(0).getResolvableErrors().get(0).getDefaultMessage();
return ResponseEntity.badRequest().body(msg);
}
📌 全局统一处理建议(推荐用于 Spring Boot 3+)
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleInvalid(MethodArgumentNotValidException ex) {
String msg = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
return ResponseEntity.badRequest().body(msg);
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handleConstraint(ConstraintViolationException ex) {
String msg = ex.getConstraintViolations().iterator().next().getMessage();
return ResponseEntity.badRequest().body(msg);
}
@ExceptionHandler(HandlerMethodValidationException.class)
public ResponseEntity<?> handleHandler(HandlerMethodValidationException ex) {
String msg = ex.getAllValidationResults().get(0).getResolvableErrors().get(0).getDefaultMessage();
return ResponseEntity.badRequest().body(msg);
}
}
✅ 异常类型对比总结
异常 | 作用范围 | 出现场景 | Spring 版本 |
---|
MethodArgumentNotValidException | @RequestBody | DTO 参数校验失败 | Spring Boot 2/3 |
ConstraintViolationException | 基本类型参数 | 方法参数、@RequestParam | Spring Boot 2/3 |
HandlerMethodValidationException | 方法级统一封装 | Controller / Service 方法参数 | Spring Boot 3 / Spring 6 |