在 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 |
通过合理使用这些注解,可以轻松实现参数校验,提高代码健壮性! 🚀