可参数化的JSR-303验证值

时间:2011-08-04 09:19:53

标签: java spring bean-validation

我使用JSR-303 bean验证和Spring 3,我需要根据用例为注释提供不同的值。

例如,min@Size(min=?)参数的值对于某些验证必须为1,对于另一种情况必须为5,我想从属性文件中读取此值。

我知道如果作为密钥提供,可以从ValidationMessages.properties文件中读取消息参数,但是其他参数呢?

2 个答案:

答案 0 :(得分:3)

注释参数的值只能是编译时表达式。这意味着对于@Size(min=X, max=Z) X和Z必须在编译时可解析。

由于minmaxint上被声明为@Size,因此您被卡住了。

如果min需要不同的值,我个人会看到两种方法

首先,您可以在验证器上使用分组。将一个组用于min=1,将一个组用于min=5。例如,我们考虑一个Test类:

public class Test {
  @NotNull
  @Size.List({
     @Size(min = 1, groups = GroupOne.class),
     @Size(min = 5, groups = GroupTwo.class)
  })
  private String prop;

  public String getProp() {
     return prop;
  }
  public void setProp(String prop) {
     this.prop = prop;
  }
}

您必须声明群组:

public interface GroupOne {}
public interface GroupTwo {}

然后创建一些测试对象加上验证器来配合它:

Test test = new Test();
test.setProp("XY");

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

然后使用组进行验证:

Set<ConstraintViolation<Test>> resultOne = validator.validate(test, GroupOne.class);
Set<ConstraintViolation<Test>> resultTwo = validator.validate(test, GroupTwo.class);

第一种情况从min=1"XY".length() == 2开始有效,但第二种情况会失败,因为min=5

此方法涉及手动进行验证,我认为您不能仅依靠@Valid带注释的@RequestMapping方法进行验证(因为@Valid只是一个触发器用于验证而无需提及所需的验证组)。幸运的是Spring非常灵活,自己调用验证器也不会有太大的开销。

我看到的第二个选项涉及使用要匹配的自定义验证程序创建自己的验证注释。 Here you can find a simple example to get you started。使用此解决方案,您可以将minmax声明为验证程序在验证之前将在解决方案中解析的字符串键。虽然这个解决方案比第一个解决方案更有开销。

答案 1 :(得分:3)

如dpb所述,您可以使用validation groups指定具有不同属性值的相同约束。

如果您正在使用Hibernate Validator作为BV实施,那么您可以使用programmatic API而不是注释来定义约束。这样你就可以在运行时检索具体的约束值,如下所示:

int minValue1 = ...; //read from properties file etc.
int minValue2 = ...;

//programmatically define the constraints for the Test type
ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Test.class )
    .property( "prop", FIELD )
        .constraint( new NotNullDef() )
        .constraint( new SizeDef().min( minValue1 ).groups( GroupOne.class ) )
        .constraint( new SizeDef().min( minValue2 ).groups( GroupTwo.class ) );

//retrieve a validator using the programmatic constraint mapping
HibernateValidatorConfiguration config = 
    Validation.byProvider( HibernateValidator.class ).configure();
config.addMapping( mapping );
ValidatorFactory factory = config.buildValidatorFactory();
Validator validator = factory.getValidator();