验证器、转换器
同一namespace下的tag不能定义到多个文件中,不支持模块化
<facelet-taglib>
??? ? ??? <!-- all custom tag-->
??? <namespace>http://www.acca.com/validator</namespace>
??? <tag>
??? ??? <tag-name>formCodeRangeValidator2</tag-name>
??? ??? <validator>
??? ??? ??? <validator-id>formCodeRangeValidatorId2</validator-id>
??? ??? </validator>
??? </tag>
</facelet-taglib>
?
慎用基于组件seam的Converter,Validatorseam允许将seam组件作为jsf Converter,Validator使用,参见满江红文档。这样不需要在faces-config.xml中配置 Converter,Validator,就可以直接使用,问题是只能创建一个实例,如果在一个页面内同时使用了多个相同的验证或转换器,那么也只有一个实例,后面的属性设置会覆盖前面的属性设置。如下所示formValidator验证实例只有一个,validateMethod的属性值是bspSysProviderAction.validate22()。
<h:inputHidden value="hiddenValidator">
??? ??? ??? <vali:formValidator validateMethod="bspSysProviderAction.validate()"/>
??? ??? ??? <vali:formValidator validateMethod="bspSysProviderAction.validate22()"/>
</h:inputHidden>
?
原本的jsf规范要求每次使用验证器就要创建一个验证器实例,上面的示例应该有两个formValidator实例,每个实例有自己的validateMethod属性。
如果系统中存在使用多个实例的验证、转换器就不要使用seam的Converter,Validator。
seam提供的EntityConverter(s:convertEntity)整个系统只需要一个实例即可。
hibernate验证在jsf中的错误???jsf对页面输入域的不提交和输入空值是两种不同的处理,不提交的字段获取的值是null,输入空的提交字段获取的值是空字符串,当获取值是null时就不进行验证,获取值是空字符串时还有进行requried验证。
UIInput?
public void validate(FacesContext context) {
??????? Object submittedValue = getSubmittedValue();
??????? if (submittedValue == null) {
??????????? return;
??????? }
hibernate验证只对null进行处理,空字符串不处理。当页面输入空字符串时jsf验证没有错误(包括jsf调用的hibernate验证),但是hibernate本身存储时执行验证会出错。
@Length
public boolean isValid(Object value) {
??if ( value == null ) return true;
?。。。。?}
修改办法:1)重写hibernate验证实现,增加""判断,2)在实体属性上处理,set方法中判断“”就设为null。
一个组件上支持多个验证一个组件上支持多个验证,但只能支持一个转换器。
如下所示,可以添加一个validator属性验证器,和多个标签验证,他们按照页面内出现的顺序执行,示例中就是按如下顺序执行1)commissionTaxAction.checkBeforeSubmit 2)isss:taxTypeValidator 3)isss:dateGroupValidator
<h:inputText value="#{hiddenValidator.value}"? validator="#{commissionTaxAction.checkBeforeSubmit}">
????????<isss:taxTypeValidator />
????<isss:dateGroupValidator eleId="startDate" refId="endDate" />?
????</h:inputHidden>
默认情况下这些验证器都会被执行,不管是不是有验证器失败了,如果想让一个验证器失败了后就不再继续执行其他的验证器,就必须在验证器内部进行特定处理。
验证之前先判断组件Valid是不是有效,验证失败后设置Valid为失败,这样下一个验证器就不好执行了。
示例代码如下
if (!ui.isValid()) {
????return;
???}
if(验证失败){
ui.setValid(false);
throw new ValidatorException。。。
}
seam集成的hibernate验证问题seam集成的hibernate验证只能在没有验证器的情况下使用,如果组件上已存在了验证器,那么hibernate验证器是加不到组件上面的,重新实现ValidateAllRendererBase的addValidators方法
private void addValidators(List children) {
??for (Object child : children) {
???if (child instanceof EditableValueHolder) {
????EditableValueHolder evh = (EditableValueHolder) child;
//????if (evh.getValidators().length == 0) {//注释的代码表示组件上没有验证器时才能添加hibernate验证
//?????evh.addValidator(new ModelValidator());
//????}
????List<Validator> vList = new ArrayList<Validator>(//修改过后的代码保证将hibernate验证加在所有验证器的前面
??????evh.getValidators().length + 1);
????for (Validator va : evh.getValidators()) {
?????vList.add(va);
?????evh.removeValidator(va);
????}
????evh.addValidator(new ModelValidator());
????for(Validator va : vList){
?????evh.addValidator(va);
????}
???}
???addValidators(((UIComponent) child).getChildren());
??}
?}
?