后构造方法中的约束验证

Constraints validation in a postconstruct method

你好我有下一段代码:

@Setter
@Getter
@Builder
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  public User(String username){
    this.username = username;
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

它正在工作,当我尝试创建一个用户时,它总是检查约束(也使用构建器模式),但我想避免生成构造函数并使用 lombok 注释 @AllArgsConstructor 并使用 PostConstruct从 javax 到验证。

@Setter
@Getter
@AllArgsConstructor
@Builder
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @PostConstruct
  public void valid() {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

我正在使用 JAVA11 包括 javax.annotation 依赖项。 User是一个常规对象,不是spring的bean。 但是这种方式行不通......我怎样才能让它发挥作用?谢谢

如果您使用 java 版本的 9 或更高版本,@PostConstruct 已弃用,因此您可能需要手动添加依赖项。您可以添加您使用的 java 版本吗?

它不起作用的另一个原因是因为您没有应用 @Component 注释并且 @PostConstruct 仅适用于由 spring 容器管理的 bean。

参考:Why is PostConstruct not called?

我建议您查看 BeanPostProccessor for AOP,因为它更灵活并且允许您对 bean 进行验证。这也是pure aop.

我终于找到了我要找的行为。

@Setter
@Getter
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @Builder
  public User(String username){
    this.username = username;
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

此外,我将实现一个可自我验证的 class 以供重用。

public abstract class SelfValidating < T > {
    private Validator validator;
    public SelfValidating() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }
    protected void validateSelf() {
        Set < ConstraintViolation < T >> violations = validator.validate((T) this);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
}

然后,我的用户 class 会:

@Setter
@Getter
public class User extends SelfValidating<User> {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @Builder
  public User(String username){
    this.username = username;
    this.validateSelf();
}

这个想法来自Get Your Hands Dirty on Clean Architecture