介绍
在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。如果有大神知情者,还请指教,谢谢!