插件开发-苍穹自定义校验器执行解析原创
金蝶云社区-希文
希文
7人赞赏了该文章 1762次浏览 未经作者许可,禁止转载编辑于2022年09月07日 17:07:01

问题:

单据中设置一个字段必录比如 fieldA,提交操作中开启了非空必录校验(保存不校验),自定义操作插件也通过

onAddValidators 添加 自定义校验器对fieldA进行特殊逻辑校验 。当提交时,如 fieldA 为空,并且自定义校验器对fieldA 
使用前如未判空,则报错。

需求:

如果页面配置的校验器不通过,则不走自定义校验器校验逻辑。


思路与方案

首先需要了解苍穹校验器的执行逻辑,很多同学通过上面描述可以会认为自定义的校验器会首先执行,实际情况是先执行

校验规则列表上面的校验器(包括动态注册的自定义校验器),后再执行操作插件中的自定义校验器,并且所有校验器都会

执行,并不会因为校验规则列表上面的校验器执行不通过就不执行操作插件中的自定义校验器,所以导致的上述问题

image.png


源码解读校验器执行流程

首先,先了解校验器添加逻辑,添加校验器由EntityOperateService 实现

image.png

可以发现,校验器存放在有序列表中,添加后校验器的校验结果都是success 的,后续执行才修改校验结果,默认顺序为界面的校验器在前,操作插件中的校验器在后

注意:,此时只是单纯获取到所有校验器并添加到列表中,启动每个校验器的校验规则还没有执行,也就是说,

还没有执行

AbstractValidator中  validate() 方法

那具体执行是在什么时候呢

来到 ValidationService ,看代码,可以知道其通过 validate(ValidateContext validateContext) 
一步一步执行到 AbstractValidator中  validate() 方法


public ValidateResultCollection validate(ValidateContext validateContext) {
    if (this.validators.isEmpty()) {
        return new ValidateResultCollection();
    } else {
        //...
        this.validators.sort(new ValidatePriorityComparator());//此处做排序,无特殊配置顺序不变
        Iterator var6 = this.validators.iterator();

        while(var6.hasNext()) {
        //....
        }

       // ...

        return this.validate(validateContext, this.validators);
    }
}


private ValidateResultCollection validate(ValidateContext validateContext, List<AbstractValidator> validators) {
    ...
    //开始按顺序遍历执行
    Iterator var6 = validators.iterator();
    while(true) {
        AbstractValidator validator;
        do {
            if (!var6.hasNext()) {
              ...
              return validateResults;
            }

            validator = (AbstractValidator)var6.next();
        } while((ignoreInteraction || ignoreWarn) && validator.getErrorLevl() == ErrorLevel.Warning);

        this.doVaidate(validator, validateResults);
    }
}
private void doVaidate(AbstractValidator validator, ValidateResultCollection validateResults) {
            //...
            validator.validate(); // 此处调用  validate() 方法,并且可以会修改校验器的校验结果
            ValidateResult res = validator.getValidateResult();
            if (!res.isSuccess()) {
                //校验不成功是添加校验错误信息
           // ...
            }
            //....
}

到此所有校验器全部执行完,同时可以知道每个校验器的执行结果,通过源码可以知道操作插件中的校验器一般为最后执行。


所以,来到最初问题,如何 

如果页面配置的校验器不通过,则不走自定义校验器校验逻辑。


很简单,如下所示 

image.png

赞 7