32.3. <ajax:clientValidator>

JSF提供了标准的数据转换与验证框架,可以满足大部分的表单处理要求,同时确保数据模型的完整性。由于将数据转换和验证的代码与正常处理逻辑代码有效地分离,使代码的可维护性大为增强。但JSF的数据转换与验证是在服务器端进行的,对于一些简单的数据校验来说这种方式增大了网络的开销,因此我们应当想办法使数据校验尽可能在客户端完成。

Apusic OperaMasks对标准数据转换与验证框架进行了扩充,使大部分转换器与校验器都可以在客户端进行。这是在渲染一个页面时生成同服务器端转换与校验器完全等价的客户端Javascript代码来实现的。要使用客户端数据校验,可以将w:form标签的clientValidate属性设置为true,或者在web.xml中将参数org.operamasks.faces.CLIENT_VALIDATE的值设置为true。前者仅对指定的form有效,后者对整个web应用都将执行客户端校验。 支持客户端数据校验的标准转换器与校验器包括如下:

javax.faces.convert.ByteConverter javax.faces.convert.DoubleConverter

javax.faces.convert.FloatConverter javax.faces.convert.IntegerConverter

javax.faces.convert.LongConverter javax.faces.convert.ShortConverter

javax.faces.validator.DoubleRangeValidator javax.faces.validator.LengthValidator

javax.faces.validator.LongRangeValidator

对自定义的转换器和校验器如果想提供客户端校验能力,可以实现org.operamasks.faces.validator.ClientValidator接口, 这个接口包括两个方法:

String getValidatorScript(FacesContext context, UIComponent component);生成一个Javascript代码,这段代码将定义一个客户端校验器对象。在ajax.js脚本文件中有关于客户端校验器的完整定义。

String getValidatorInstanceScript(FacesContext context, UIComponent component);生成一个Javascript代码,这段代码将创建一个在上个方法中定义的客户端校验器对象,完成对客户输入数据的校验。另外,也可以将校验器的定义放在一个单独的脚本文件中,这样getValidationScript方法可以返回null,而不必每次都包含相同的脚本。

32.3.1. 构件信息

表 32.4. 构件信息

Tag Classorg.operamasks.faces.webapp.ajax.ClientValidatorTag

继承体系

32.3.2. 属性

表 32.5. 属性

message 定义类
类型 javax.el.ValueExpression(java.lang.String)
是否必须 延时求值
验证失败时的错误消息

32.3.3. 构件API

32.3.4. 例子

下面的例子使用一个正则表达式对客户输入数据进行校验,它同时实现Validator和ClientValidator接口完成服务器端和客户端的校验。注意,由于客户端校验很容易被有经验的客户所绕过,因此服务器端的校验是必须的。

public class RegExpValidator implements Validator, ClientValidator {
    private String pattern;

    public void setPattern(String patter){
        this.pattern = pattern;
    }

    public void validate(FacesContext context, UIComponent component,
            Object value) throws ValidationException {
        // 执行服务器端数据校验
    }

    public String getValidatorScript(FacesContext context, UIComponent component) {
        return
            "function RegExpValidator(id,message,pattern) { +
                "this._id = id;" +
                "this._message = message;" +
                "this._pattern = pattern;" +
            "}" +
            "RegExpValidator.prototype = new Validator();" +
            "RegExpValidator.prototype.validate =
            function(value) {" +
                "var re = new RegExp(this._pattern);" +
                "return re.test(value);" +
            "}";
    }
    
    public String getValidatorInstanceScript(FacesContext context, UIComponent component) {
        String id = component.getClientId(context);
        String message = "Regular expression validation error.";
        String pattern = this.pattern;
        return "new RegExpValidator('" + id + "', '" + message + "', '" + pattern + "')";
    }
}    

如果不想写一个单独的校验器,也可以使用ajax:clientValidate标签将Javascript代码直接嵌入JSP页面,这对一些并不具有通用性的数据校验比较方便。下面是一个例子:

<h:form clientValidate="true">
  <h:inputText value="#{UserBean.phoneNumber}" validator="#{UserBean.validatePhoneNumber}">
    <ajax:clientValidator message="Invalid phone number">
      var re = new RegExp("/^0\d{1,3}-\d{3}-\d{4}$/"); return re.test(value);
    <ajax:clientValidator>
  </h:inputText> 
</h:form>

其中UserBean.validatePhoneNumber在Managed Bean中实现,执行服务器端校验,ajax:clientValidateor标签的内容是一段Javascript脚本,执行客户端校验,输入值是value,返回值必须是true或false。