代码之家  ›  专栏  ›  技术社区  ›  Alireza Fattahi

如何短路@CustomValidator?

  •  2
  • Alireza Fattahi  · 技术社区  · 9 年前

    考虑下面的示例,它检查 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 这个 日期验证程序 s、 但是 比较日期验证程序 总是运行,这是不正确的。我能修好吗?!

    1 回复  |  直到 9 年前
        1
  •  2
  •   Community uzul    7 年前

    正如所解释的 in the documentation .

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

    那么您的实际执行顺序是:

    1. 比较日期验证程序 (平原)
    2. 日期验证程序 (字段 fromDate )
    3. 日期验证程序 (字段 toDate )

    问题是它将首先执行,但由于它的检查是基于两个字段的复合检查,因此应该首先执行字段本身的原子检查。

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

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

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

    你只需要记住 现场验证程序 在相同的验证堆栈中 比较日期验证程序 ,或 “日期无效” 错误将被默默吞没。