ADF11g-027:自定义JSF Validator

介绍

在ADF中,我们有很多方式给组件添加验证。

1.直接在组件的validator属性上指定一个manage bean中的method

    public void validate(FacesContext context, UIComponent component,
                         Object inputValue) {
        // Add your code here...
    }

2.通过f:validator标签来指定一个实现了Validator的类,但是却无法灵活的传入参数,例如

<f:validator validatorId="javax.faces.DoubleRange"/>

3.自定义一个验证标签,我们可以灵活指定它的各种参数,如错误message,条件等。这也是本文需要描述的内容:自定义一个标签,打成jar包,可以在任何一个ADF项目中引用,可以灵活指定参数等,完成验证某数是否为指定数字的倍数的功能

<af:inputText label="30的倍数" id="it3" autoSubmit="true"
                        validator="#{ValidatorBean.validate}">
            <afcv:validateMultipleNumber multiple="30"
                                         messageDetailNotMultiple="自定义消息"/>
            <af:convertNumber/>
          </af:inputText>

步骤

1.创建ADF应用,应用目录结构如下



2.编写MultipleNumberValidator类和对应的Tag类逻辑

package adf.validator;

import javax.el.ValueExpression;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import org.apache.myfaces.trinidad.util.MessageFactory;
import org.apache.myfaces.trinidadinternal.taglib.util.TagUtils;

public class MultipleNumberValidator implements Validator {
    
    /**
     * 常量,validator id
     */
    public static final String VALIDATOR_ID = "adf.validator.MultipleNumberValidator";
    
    /**
     * 对应资源文件中的key
     */
    public static final String MULTIPLE_MESSAGE_ID = "adf.validator.MultipleNumberValidator.MULTIPLE";
    
    /**
     * 倍数
     */
    private ValueExpression _multiple;
    /**
     * 验证不通过时的消息
     */
    private ValueExpression _messageDetailNotMultiple;
    
    private Double _multipleValue;
    
    public MultipleNumberValidator() {
        super();
    }
    /**
     * 实现验证逻辑
     * @param context
     * @param component
     * @param value 输入值
     * @throws ValidatorException
     */
    @Override
    public void validate(FacesContext context, UIComponent component,
                         Object value) throws ValidatorException {
        if(_multipleValue == null) {
            _multipleValue = getDoubleValue(context, _multiple);
        }
        Double inputValue = null;
        if (value instanceof java.lang.Number) {
            inputValue = (((Number)value).doubleValue());
        } else {
            inputValue = Double.valueOf(value.toString());
        }
        if(_multipleValue != null && inputValue != null) {
            if(inputValue % _multipleValue != 0) {
                throw new ValidatorException(_getMultipleMessage(context,
                                                                 component, value,
                                                                 _multipleValue));
            }
        }
    }
    
    /**
     * 获取消息资源
     * @param context
     * @param component
     * @param value
     * @param multiple
     * @return
     */
    private FacesMessage _getMultipleMessage(FacesContext context,
                                             UIComponent component,
                                             Object value, Object multiple) {
        Object message = null;
        if (_messageDetailNotMultiple != null) {
            message =
                    _messageDetailNotMultiple.getValue(context.getELContext());
        }
        Object[] params = {value, multiple};

        //系统会根据MULTIPLE_MESSAGE_ID自动找到summary和detail message
        //detail message的key命名方式是在summary key的命名后面加 "_detail" 后缀
        return MessageFactory.getMessage(context, MULTIPLE_MESSAGE_ID, message,
                                         params, component);
    }
    
    private Double getDoubleValue(FacesContext context, ValueExpression ve) {
        if(ve == null) {
            return null;
        }
        Object value = ve.getValue(context.getELContext());
        if(value != null) {
            return TagUtils.getDouble(value);        
        } 
        return null;
    }
    
    public void setMultiple(ValueExpression _multiple) {
        this._multiple = _multiple;
    }
    
    
    public ValueExpression getMultiple() {
        return _multiple;
    }

    public void setMessageDetailNotMultiple(ValueExpression _messageDetailNotMultiple) {
        this._messageDetailNotMultiple = _messageDetailNotMultiple;
    }

    public ValueExpression getMessageDetailNotMultiple() {
        return _messageDetailNotMultiple;
    }

    public void setMultipleValue(Double _multipleValue) {
        this._multipleValue = _multipleValue;
    }

    public Double getMultipleValue() {
        return _multipleValue;
    }
}
package adf.validator;

import javax.el.ValueExpression;

import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.webapp.ValidatorELTag;

public class MultipleNumberValidatorTag extends ValidatorELTag {
    
    private ValueExpression _multiple;
    private ValueExpression _messageDetailNotMultiple;
    
    public MultipleNumberValidatorTag() {
        super();
    }
    
    /**
     *创建Validator实例
     * @return
     */
    @Override
    protected Validator createValidator() {
        String validatorId = MultipleNumberValidator.VALIDATOR_ID;
        //使用这种方式创建validator实例时,必须在faces-config.xml中配置validator
        //也可以直接使用new关键字创建一个validator实例
        Application appl = FacesContext.getCurrentInstance().getApplication();
        MultipleNumberValidator validator = (MultipleNumberValidator)appl.createValidator(validatorId);
        validator.setMultiple(_multiple);
        validator.setMessageDetailNotMultiple(_messageDetailNotMultiple);
        return validator;
    }

    public void setMultiple(ValueExpression _multiple) {
        this._multiple = _multiple;
    }

    public ValueExpression getMultiple() {
        return _multiple;
    }

    public void setMessageDetailNotMultiple(ValueExpression _messageDetailNotMultiple) {
        this._messageDetailNotMultiple = _messageDetailNotMultiple;
    }

    public ValueExpression getMessageDetailNotMultiple() {
        return _messageDetailNotMultiple;
    }
}

3.创建tld文件


<?xml version = '1.0' encoding = 'UTF-8'?>
<taglib xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1" xmlns="http://java.sun.com/xml/ns/javaee">
  <display-name>ADF Custom Validators</display-name>
  <tlib-version>1.0</tlib-version>
  <short-name>afcv</short-name>
  <uri>http://blog.csdn.net/ygj26/adf/afcv</uri>
  <tag>
    <description>倍数验证</description>
    <name>validateMultipleNumber</name>
    <tag-class>adf.validator.MultipleNumberValidatorTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
      <name>id</name>
    </attribute>
    <attribute>
      <name>multiple</name>
      <deferred-value>
        <type>java.lang.Object</type>
      </deferred-value>
    </attribute>
    <attribute>
      <name>messageDetailNotMultiple</name>
      <deferred-value/>
    </attribute>
  </tag>
</taglib>

4.创建并配置国际化资源文件以及配置validator

英文

adf.validator.MultipleNumberValidator.MULTIPLE={0} is not a multiple of {1}.
adf.validator.MultipleNumberValidator.MULTIPLE_detail={0} is not a multiple of {1}, this value must be a multiple of {1}.
中文

adf.validator.MultipleNumberValidator.MULTIPLE=不正确的倍数
adf.validator.MultipleNumberValidator.MULTIPLE_detail={0}不是{1}的倍数,该数必须是{1}的倍数
faces-config.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee">
  <application>
    <default-render-kit-id>oracle.adf.rich</default-render-kit-id>
    <message-bundle>adf.validator.resources.ValidateMessage</message-bundle>
  </application>
  <validator>
    <validator-id>adf.validator.MultipleNumberValidator</validator-id>
    <validator-class>adf.validator.MultipleNumberValidator</validator-class>
  </validator>
</faces-config>
5.部署

创建ADF Library部署文件



应用

1.在ADF的Project中引入上面步骤中创建的tag


2.创建测试页面

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:afcv="http://blog.csdn.net/ygj26/adf/afcv">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document id="d1">
      <af:form id="f1">
        <af:messages id="m1" inline="true"/>
        <af:panelFormLayout id="pfl1">
          <f:facet name="footer"/>
          <af:inputText label="10的倍数" id="it1" autoSubmit="true">
            <afcv:validateMultipleNumber multiple="10"/>
            <af:convertNumber/>
          </af:inputText>
          <af:inputText label="20的倍数" id="it2" autoSubmit="true">
            <afcv:validateMultipleNumber multiple="#{20}"/>
            <af:convertNumber/>
          </af:inputText>
          <af:inputText label="30的倍数" id="it3" autoSubmit="true"
                        validator="#{ValidatorBean.validate}">
            <afcv:validateMultipleNumber multiple="30"
                                         messageDetailNotMultiple="自定义消息"/>
            <af:convertNumber/>
          </af:inputText>
        </af:panelFormLayout>
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

说明

1.现在的验证还不能像ADF已有的验证组件一样在客户端进行验证,而需要submit之后才能触发验证。此功能牵扯到JavaScript的相关内容,如后期有完善功能再写入文章。
2.在某些使用EL表达式设定参数情况下(具体情况不名),就是不能触发验证,debug代码时发现multiple属性为null。如果有大神知情者,还请指教,谢谢!

代码下载

参考文献

Creating Custom JSF Validation

Using the JSF Lifecycle with ADF Faces

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值