3.5.2.4.5. 验证器控件

Validator 设计用来检查可视化组件中输入的值。

验证和输入检查是需要区分开来的,输入检查是说:假设一个文本组件(比如,TextField)的数据类型设置的不是字符串(这种情况可能出现在绑定实体属性或者手动设置控件的 datatype ),那么这个组件会阻止用户输入不符合它定义的数据类型的值。当这个组件失去焦点时或者用户按了回车,这个组件会显示之前正确的值。

验证不会在输入同时或者失去焦点时马上反馈,而是会在组件的 validate() 方法调用的时候。也就是说这个组件(还有这个组件关联的实体属性)暂时会包含一个可能并不符合验证规则的值。但是这没关系,因为需要验证的字段一般都会在编辑界面,所有的字段提交前会自动调用验证方法。如果组件不在一个编辑界面,那么这个组件的 validate() 方法需要在界面控制器显式的调用。

在界面的 XML 描述中,组件的验证器可以在嵌套的 validator 元素中定义。validator 元素可以有这些属性:

  • script − Groovy 脚本的路径。这个脚本用来做验证。

  • class − 实现了 Field.Validator 接口的 Java 类名。

Groovy 验证脚本和标准 Java 验证器类,位置在 com.haulmont.cuba.gui.components.validators 包,支持 message 属性,用来定义验证失败时显示的消息。这个属性的值可以是包含消息内容的字符串或者一个当前界面语言消息包内的一个消息键名。比如:

<validator class="com.haulmont.cuba.gui.components.validators.PatternValidator"
           message="msg://validationError"
           pattern="\d{3}"/>
# messages.properties
validationError = Input error

可以通过 CUBA Studio 添加验证器。下面是给 fieldGroup 组件添加验证器的例子:

gui validator

验证机制是按如下方式确定的:

  • 如果 script 属性的值没有设置,并且 validator 元素也没有包含 Groovy 表达式的文本,系统会使用 class 属性定义的类来进行验证。

    <field property="amount">
        <validator class="com.haulmont.cuba.gui.components.validators.DoubleValidator"/>
    </field>
  • 如果 validator 元素包含了文本,那这个文本会被当作 Groovy 表达式通过 Scripting 来执行。

    <field property="year">
        <validator>
            value ==~ /\d+/
        </validator>
    </field>
  • 否则,系统会使用 Scripting 来运行定义在 script 里的 Groovy 脚本。

    <field property="zipCode">
        <validator script="com.company.demo.web.address.ZipValidator"/>
    </field>

变量 value 会被传入 Groovy 表达式或者脚本,这个值包含了可视化组件中用户输入的值。表达式或者脚本需要返回一个 boolean 值: true 表示验证通过,false 表示没通过。

如果使用 Java 类作为验证器,这个类要么有一个不带任何参数的默认构造函数,要么有带有如下参数组合的构造函数:

  • org.dom4j.Element, String – 这个构造函数会接收验证器的 XML 元素和界面消息包的名字。

  • org.dom4j.Element – 这个构造函数会接收验证器的 XML 元素。

如果验证器是用内部类的方式实现的,这个类需要是 static 的,名字用 "$" 跟外部类分隔,比如:

<validator class="com.sample.sales.gui.AddressEdit$ZipValidator"/>

平台已经包含了一组常用的验证器实现(参考 com.haulmont.cuba.gui.components.validators 包),可以在项目里使用:

  • DateValidator - 日期验证

  • DoubleValidator - 双浮点数验证

  • EmailValidator - 邮件地址验证

  • IntegerValidator - 整数类型验证

  • LongValidator - 长整型验证

  • PatternValidator - 正则模式验证

  • ScriptValidator - 脚本验证

  • StringValidator - 字符串类型验证

验证器不仅可以通过嵌套的 XML 配置给组件,也可以通过编程的方式 - 通过提交一个验证器实例给组件的 addValidator() 方法。

下面的例子就是以编程方式创建了一个邮编的验证器类:

public class ZipValidator implements Field.Validator {
    @Override
    public void validate(Object value) throws ValidationException {
        if (value != null && ((String) value).length() != 6)
            throw new ValidationException("Zip must be of 6 characters length");
    }
}

下面例子演示在 FieldGroup 组件使用邮编验证器和标准的正则模式验证器:

<fieldGroup>
    <field property="zip" required="true">
         <validator class="com.company.sample.gui.ZipValidator"/>
    </field>
    <field property="imei">
        <validator class="com.haulmont.cuba.gui.components.validators.PatternValidator"
               pattern="\d{15}"
               message="IMEI validation failed"/>
    </field>
</fieldGroup>

这个是在界面控制器中以编程方式设置验证器:

if (Boolean.TRUE.equals(parameter.getRequired())) {
    tokenList.addValidator(new Field.Validator() {
        @Override
        public void validate(Object value) throws ValidationException {
            if (value instanceof Collection && CollectionUtils.isEmpty((Collection) value)) {
                throw new ValidationException(getMessage("paramIsRequiredButEmpty"));
            }
        }
    });
}