如何使@CustomValidator短路?

时间:2015-12-23 13:11:47

标签: java validation struts2 struts-validation struts2-convention-plugin

请考虑以下示例,该示例会检查fromDatetoDate是否为有效日期,且fromDate是否小于toDate

@CustomValidator(type = "DateValidator", 
            fieldName = "fromDate",
         shortCircuit = true),

@CustomValidator(type = "DateValidator", 
            fieldName = "toDate",
         shortCircuit = true),

@CustomValidator(type = "CompareDatesValidator", 
              message = "validate.date.jalali.same.or.before",
         shortCircuit = true, 
           parameters = {
        @ValidationParameter(name = "fromDateParam", value = "${fromDate}"),
        @ValidationParameter(name = "toDateParam", value = "${toDate}") 
               })

DateValidator扩展了FieldValidatorSupport,而CompareDatesValidator扩展了ValidatorSupport

虽然shortCircuit DateValidator CompareDatesValidator,但int总是运行,这是不正确的。我能解决这个问题吗?!

1 个答案:

答案 0 :(得分:2)

正如in the documentation所述。

  

普通验证器优先于字段验证器。它们首先按照它们的定义顺序进行验证,然后按照它们的定义顺序进行字段验证。标记为短路的特定验证器失败将阻止对后续验证器的评估,并且将错误(操作错误或字段错误(取决于验证器的类型)添加到要验证的对象的ValidationContext中。

然后您的实际执行顺序为:

  1. CompareDatesValidator (普通)
  2. DateValidator (字段fromDate
  3. DateValidator (字段toDate
  4. 问题在于它将首先执行,但由于它的检查是基于两个字段的复合检查,因此应首先对字段本身进行原子检查。

    但这就是框架的工作原理,所以你需要解决方法

    如果your plain validator is still this one(即使使用some modification),您可以避免检查并在输入无效的情况下忽略错误,让此验证发生在它所属的位置,在字段验证器中:

    public final class CompareDatesValidator extends ValidatorSupport {
        private String fromDate; // getter and setter
        private String toDate;   // getter and setter    
    
        @Override
        public void validate(Object o) throws ValidationException {
            Date d1 = (Date)parse(fromDate, Date.class);
            Date d2 = (Date)parse(toDate, Date.class);
    
            if (d1==null || d2==null){
                LOG.debug("Silently disabling Plain Validator. Check performed by Field ones");
            } else if (d2.before(d1)){
                addActionError(getDefaultMessage());
            }
        }
    }
    

    您只需要记住始终将字段验证器放在 CompareDatesValidator 的相同验证堆栈中,或者“日期无效”将无声地吞下错误。