【问题标题】:Parametrizable JSR-303 validation values可参数化的 JSR-303 验证值
【发布时间】:2011-08-04 09:19:52
【问题描述】:

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

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

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

【问题讨论】:

    标签: java spring bean-validation


    【解决方案1】:

    如 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();
    

    【讨论】:

      【解决方案2】:

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

      由于minmax@Size 上被声明为int,所以你被卡住了。

      如果您需要 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 声明为字符串键,您的验证器将在验证之前在包中解析它们。这个解决方案虽然比第一个解决方案开销更大。

      【讨论】:

      • 我确实认为自定义注释+验证器是这里的方式。他可以实现一个 @DynMin 注释,该注释将被称为 `@DynMin(min = "{my.property.somewhere}") 并使用自定义验证器类,该类将读取属性并验证它(使用参考实现验证器,例如)。
      猜你喜欢
      • 2015-01-10
      • 1970-01-01
      • 2011-10-30
      • 2018-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 2011-06-09
      相关资源
      最近更新 更多