不使用注解的编程式Bean验证(JSR 303)

9

可能是重复问题:
不调用注释使用Hibernate验证器。

我有这个组合约束注释(仅供说明):

@Target... @Retention...
@Constraint(validatedBy = {})
@Pattern(regexp = PasswordComplexity.AT_LEAST_TWO_NONE_ALPAH_CHARS)
@Length(min = 6, max = 20)
public @interface PasswordComplexity {   
    ...    
}

我在Spring Controllers和Entity Classes中使用它。

但是现在我需要在Service方法中检查单个字符串,在这里我需要将相同的约束应用于一个单个字符串。由于约束是相同的,我想使用相同的约束定义(@PasswordComplexity)(唯一真理来源)。类似于:

public void createUser(UserDto userDto, String password) {
  if(hasViolation(validator.validate(password,PasswordComplexity.class))) {
   throw new PasswordComplexityViolationException();
  } else {
   …
  }
}

但我不知道如何为未注释的简单对象(String)运行JSR 303验证器。这是否至少是可能的,如何实现?

(我使用Hibernate Validator作为JSR 303提供者)


我理解你所说的“单一真相来源”是指不必重复在 UserDto 类中的 password 属性/字段上方放置的注释,对吗?但是在你的“类似于”的示例中,至少重复了注释的名称(PasswordComplexity)。这也不是多余吗? - Grzegorz Oledzki
@Grzegorz Oledzki:不,问题不在于在不同的地方编写使用注释。所谓“单一真相来源”,是指我想使用注释而不是在其他地方再次编写相同的内容(长度和模式)定义。 - Ralph
@abalogh:这个问题是一个重复的问题(我已经忽略了它),但是被接受的答案并不符合这个问题 - 或者至少不符合我的问题。 - Ralph
1
@Grzegorz Oledzki:因为UserDto没有密码字段(也不会有)。所以我可以做的是创建一个PasswordDto,其中包含一个用@PasswordComplexity注释的password字段;在我的服务方法中从password String参数创建此PasswordDto,然后进行检查。-- 是的,这将起作用,但这是一种Hack而不是干净的代码。-- 我正在寻找一个干净、简洁、直接的解决方案。 - Ralph
@yclian:我同意,我使用了被接受的答案,因为我没有找到其他好的解决方案。无论如何,请随意创建一个新问题,并在此问题中解释与其他问题的区别。 - Ralph
显示剩余2条评论
1个回答

2
一种方法是编写完整的自定义验证器,并将逻辑推入该类中,使注释只使用验证器。这意味着您将拥有一个独立的编译单元(一个完整的类PasswordComplexityValidator implements implements ConstraintValidator<PasswordComplexity, String> ...),您可以独立于注释使用它。这种方法还可以使您更轻松地对验证进行单元测试。
但是,由于您正在使用注释作为配置Hibernate提供的现有正则表达式验证器的方式,因此您可以使用该验证器,将注释类中的常量模式传递给它。您还应该能够将长度限制打包到正则表达式中,这比使用两个注释更简单和更快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接