Spring Boot环境下使用注解实现Java类参数校验的问题咨询
需求可实现性说明
你提出的「创建对象、调用Setter传入非法参数时自动抛出校验异常」的需求完全可以实现。
现有代码存在的问题
@Validated是Spring提供的用于触发AOP切面校验的注解,仅对Spring容器管理的Bean(比如@Controller、@Service注解的类)生效,直接标注在普通User POJO类上不会自动触发校验逻辑,不管是构造对象还是调用Setter都不会抛出校验异常。- JSR-380(Bean Validation 2.0)的校验注解本身不会自动执行,需要手动调用校验器或者通过相关切面触发。
实现方案
方案1:手动触发校验(通用方案,不依赖Spring管理)
该方案不管User是不是Spring管理的Bean,只要构造对象或者调用Setter都会自动触发校验,兼容性最高。
首先确保你的Spring Boot项目引入了校验依赖:
<!-- pom.xml 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
修改后的User类代码如下:
import jakarta.validation.*; import lombok.Getter; import java.util.Set; @Getter public class User { // 初始化全局校验器 private static final Validator validator; static { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @NotBlank(message = "Username cannot be empty") private String username; @NotBlank(message = "Email address cannot be empty") @Email(message = "Please provide valid email address") private String email; @NotBlank(message = "First Name cannot be empty") private String firstName; @NotBlank(message = "Last Name cannot be empty") private String lastName; // 构造方法中执行全量校验 public User(String username, String email, String firstName, String lastName) { this.username = username; this.email = email; this.firstName = firstName; this.lastName = lastName; Set<ConstraintViolation<User>> violations = validator.validate(this); if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } } // Setter中执行单字段校验 public void setUsername(String username) { this.username = username; Set<ConstraintViolation<User>> violations = validator.validateProperty(this, "username"); if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } } public void setEmail(String email) { this.email = email; Set<ConstraintViolation<User>> violations = validator.validateProperty(this, "email"); if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } } // firstName、lastName的Setter逻辑同上,省略重复代码 }
如果你使用的是Spring Boot 2.x版本,把代码中的
jakarta.validation替换为javax.validation即可。
方案2:Spring托管Bean方案(仅适用于从容器获取User的场景)
如果你的User对象本身是Spring管理的原型Bean,可以直接用Spring的校验切面自动触发校验,无需手动写校验逻辑:
import org.springframework.validation.annotation.Validated; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Email; import lombok.Getter; import lombok.Setter; @Validated @Component @Scope("prototype") @Getter @Setter public class User { @NotBlank(message = "Username cannot be empty") private String username; @NotBlank(message = "Email address cannot be empty") @Email(message = "Please provide valid email address") private String email; @NotBlank(message = "First Name cannot be empty") private String firstName; @NotBlank(message = "Last Name cannot be empty") private String lastName; }
注意该方案仅对从Spring容器中获取的User对象生效,手动new出来的User对象不会触发自动校验。
内容的提问来源于stack exchange,提问作者Safari
相关产品推荐
相关产品推荐

