对这些校验器的功能和用法,IBM Notes and Domino Application Development wiki上有专文介绍Validation On An XPage。这些校验器用来实现特定的校验很方便,customValidator和validateExpression都可以用来添加自定义的校验逻辑。当这一切都不敷使用的时候,还能像在JSF里一样,添加以Java写的校验器。编写和在faces-config.xml里的配置与JSF里没有差别,最后选用xp:validator连接上。有兴趣的朋友可以参看JSF的相关资料。
笔者在这篇文章里主要介绍的是另一种情况下的校验。上面列举的各种校验都是在开发时已知目标栏位是哪些,对每一个提交数据的XPage都要在页面上为这些栏位逐一设置,我们不妨称之为静态校验。一个更方便的做法是在代码里集中校验,这样做校验的逻辑与界面代码分离,而且可以使程序运行时再获取要校验的栏位——同样不妨称之为动态校验——变为可能。动态校验有什么用处呢?试想在参数文档里配置和读取要校验的栏位,这样对于不同的表单就只需修改参数文档,而调用相同的代码进行校验。这样一个可配置的通用的校验“模块”可以作为一个部分整合进一个更大的可配置的流程引擎。笔者在Lotus Notes客户端和XPages的流程引擎里都是采用这样的方式。19. Notes客户机中的校验一文里介绍的用于非空校验的LotusScript类就被用来在客户端系统里进行动态校验。将这个类移植到XPages,用Java编写,就变成如下的代码。代码中的com.acme.tools.JSFUtil取自Karsten Lehmann的文章Helper classes to access the JSF environment and Lotus Notes data其中包含了获取JSF环境的诸如绑定值和视图上的组件的一些工具方法。
package starrow.xsp;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import com.acme.tools.JSFUtil;
public class Validator {
public String hint=" is required.";
Hashtable<String, String> fields;
public Validator(){
this.fields=new Hashtable<String, String>();
}
/**
* @param fieldName
* @param label
* Add a field to be checked.
*/
public void add(String fieldName, String label){
fields.put(fieldName, label);
}
/**
* @param fieldName
* Add a field which has the same label with the name.
*/
public void add(String fieldName){
add(fieldName, fieldName);
}
/**
* Return false on the first empty field.
*/
public boolean validate(){
FacesContext context=FacesContext.getCurrentInstance();
Enumeration<String> keys=fields.keys();
String key;
String msg;
FacesMessage fm;
UIInput input;
while (keys.hasMoreElements()){
key=keys.nextElement();
input=(UIInput)JSFUtil.findComponent(key);
if (input.getValue().equals("")){
msg=fields.get(key) + hint;
fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
context.addMessage(input.getClientId(context), fm);
input.setValid(false);
return false;
}
}
return true;
}
/**
* Validate all the fields. Return false if any field is empty.
*/
public boolean validateAll(){
boolean result=true;
FacesContext context=FacesContext.getCurrentInstance();
Enumeration<String> keys=fields.keys();
String key;
String msg;
FacesMessage fm;
UIInput input;
while (keys.hasMoreElements()){
key=keys.nextElement();
input=(UIInput)JSFUtil.findComponent(key);
if (input.getValue()==null || input.getValue().equals("")){
msg=fields.get(key) + hint;
fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
context.addMessage(input.getClientId(context), fm);
input.setValid(false);
result=false;
}
}
return result;
}
}
应用这个类时,要在需校验的XPage上放置一个Display Errors控件,也就是一个xp:messages。然后在提交表单的按钮里调用Validator实例的add方法添加要校验的栏位的名称和标签(界面上的栏位标题),并调用validateAll方法校验所有的添加的栏位。下面是一个校验方法里的代码片段,fields和labels是两个Vector<String>,分别装有从配置文档读取的需校验的栏位的名称和标签。
Validator v=new Validator();
for (int j=0; j<fields.size(); j++){
v.add(fields.get(j), labels.get(j));
}
return v.validateAll();
校验失败的显示效果可参考下图: