@Valid
@Valid 用于对标记的成员属性进行验证。该注解不支持分组验证。它是 Bean Validation API(JSR-303 / JSR-380) 的标准注解,属于 Java EE / Jakarta EE 规范,不是 Spring 特有。
包路径:
javax.validation.Valid(Java EE)或jakarta.validation.Valid(Jakarta EE 9+)作用:标记一个对象需要被递归验证(包括其嵌套属性)
它本身不执行验证,只是“告诉验证器:请验证这个对象”。 因此在(非Spring)项目中需要手动进行调用方法手动进行校验。但Spring 对 Bean Validation 做了深度集成,在特定场景下自动触发验证。
使用方法
依赖(以 Hibernate Validator 为例)
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.1.Final</version> <!-- Jakarta EE 9+ --> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.el</artifactId> <version>4.0.2</version> </dependency>定义带约束的实体
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; public class User { @NotBlank @Size(min = 2, max = 20) private String name; // getter/setter }手动触发验证
import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; import jakarta.validation.ConstraintViolation; import java.util.Set; public class Main { public static void main(String[] args) { // 1. 创建 Validator ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); // 2. 构造对象 User user = new User(); user.setName(""); // 违反 @NotBlank // 3. 手动验证 Set<ConstraintViolation<User>> violations = validator.validate(user); // 4. 处理结果 if (!violations.isEmpty()) { violations.forEach(v -> System.out.println(v.getPropertyPath() + ": " + v.getMessage()) ); } } }
在Spring中的使用方法
由于Spring对其进行了集成。因此在一些场景下会自动进行校验:
Controller 中的@RequestBody注解的标记的对象。
Controller 中
@ModelAttribute(表单提交)注解的标记的对象。嵌套对象验证(字段级)
Service 层方法参数(需配合
@Validated)
总结
示例
场景 1:Controller 中 @RequestBody 对象
@PostMapping("/user")
public ResponseEntity<?> createUser(@Valid @RequestBody User user) {
// 如果 user 无效,Spring MVC 会抛出 MethodArgumentNotValidException
return ResponseEntity.ok(userService.save(user));
}✅ 触发时机:参数绑定完成后、进入方法体前
✅ 必须加
@Valid(或@Validated)才能触发
场景 2:Controller 中 @ModelAttribute(表单提交)
@PostMapping("/register")
public String register(@Valid User user, BindingResult result) {
if (result.hasErrors()) {
return "register-form";
}
return "success";
}✅ 触发时机:表单数据绑定到对象后
✅ 需配合
BindingResult捕获错误(否则抛异常)
场景 3:嵌套对象验证(字段级)
public class Order {
@Valid // 👈 关键!触发 Address 的验证
private Address shippingAddress;
}
public class Address {
@NotBlank
private String street;
}✅ 触发时机:当父对象被验证时,自动递归验证带 @Valid 的字段
场景 4:Service 层方法参数(需配合 @Validated)
@Service
@Validated // 👈 启用 AOP 验证
public class UserService {
public void update(@Valid User user) {
// 若 user 无效,抛 ConstraintViolationException
}
}✅ 触发时机:方法被调用时(通过 Spring AOP 代理拦截)
❌ 必须类上有
@Validated,否则不生效
最后
@Valid本身不执行验证
它只是一个“标记”,真正的验证由 Validator 实现(如 Hibernate Validator) 执行。Spring 中的自动触发是有条件的
Controller:靠 Spring MVC 框架
Service:靠 Spring AOP(需
@Validated)
嵌套验证必须加
@Valid
否则子对象的约束不会被检查。异常类型不同
Controller(
@RequestBody)→MethodArgumentNotValidExceptionService(AOP)→
ConstraintViolationException手动验证 → 返回
Set<ConstraintViolation>
@Validated
@Validated 是 Spring Framework 提供的一个注解,用于启用方法级别(method-level)的参数验证,是对标准 Bean Validation(JSR-303/JSR-380)中 @Valid 的扩展和增强。。 该注解基于Spring AOP进行拦截进行校验。
与@Valid的区别
典型使用场景总结
其他
@Validated也可用于方法和参数上面,但最常见在Class类上使用。 如果一个Controller只需要为一个方法开启校验则只需放在该方法上但需注意:方法上的 @Validated 不能指定分组(分组只能在参数上指定,可以在方法参数内指定分组)。
评论区