JSF不支持交叉字段验证,有没有解决方法?

JSF 2.0只允许你验证一个字段的输入,比如检查是否有一定的长度。 它不允许你有一个表格,说:“输入城市和州,或只输入一个邮政编码”。

你怎么得到这个? 我只对涉及JSF验证阶段的答案感兴趣。 我不想把验证逻辑放在Managed Beans中。

我见过最简单的自定义方法是使用<f:validator>创建一个<h:inputHidden>字段,其中您引用所有涉及的组件为<f:attribute> 。 如果您待验证的组件之前声明它,那么您可以通过UIInput#getSubmittedValue()获取验证器中提交的值。

例如

 <h:form> <h:inputHidden id="foo" value="true"> <f:validator validatorId="fooValidator" /> <f:attribute name="input1" value="#{input1}" /> <f:attribute name="input2" value="#{input2}" /> <f:attribute name="input3" value="#{input3}" /> </h:inputHidden> <h:inputText binding="#{input1}" value="#{bean.input1}" /> <h:inputText binding="#{input2}" value="#{bean.input2}" /> <h:inputText binding="#{input3}" value="#{bean.input3}" /> <h:commandButton value="submit" action="#{bean.submit}" /> <h:message for="foo" /> </h:form> 

(请注意隐藏的输入上的value="true" ;实际值实际上并不重要,但要记住,验证器在空或空时不一定会被触发,具体取决于JSF版本和配置)

 @FacesValidator(value="fooValidator") public class FooValidator implements Validator { @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { UIInput input1 = (UIInput) component.getAttributes().get("input1"); UIInput input2 = (UIInput) component.getAttributes().get("input2"); UIInput input3 = (UIInput) component.getAttributes().get("input3"); // ... Object value1 = input1.getSubmittedValue(); Object value2 = input2.getSubmittedValue(); Object value3 = input3.getSubmittedValue(); // ... } } 

如果待验证的组件之后声明<h:inputHidden> ,则相关组件的值已经被转换和验证,您应该通过UIInput#getValue()或者UIInput#getLocalValue()如果UIInput不是isValid() )。

也可以看看:

  • 多个字段的验证器(针对JSF 1.2)

或者,您可以使用第三方标签/组件。 例如RichFaces有一个<rich:graphValidator>标签, Seam3为此拥有一个<s:validateForm> ,而OmniFaces有几个标准的<o:validateXxx>组件,这些都在这里展示。 OmniFaces使用基于组件的方法,在UIComponent#processValidators()完成这项工作。 它也允许以这种方式定制它,以便可以实现以上的功能:

 <h:form> <o:validateMultiple id="foo" components="input1 input2 input3" validator="#{fooValidator}" /> <h:inputText id="input1" value="#{bean.input1}" /> <h:inputText id="input2" value="#{bean.input2}" /> <h:inputText id="input3" value="#{bean.input3}" /> <h:commandButton value="submit" action="#{bean.submit}" /> <h:message for="foo" /> </h:form> 

 @ManagedBean @RequestScoped public class FooValidator implements MultiFieldValidator { @Override public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) { // ... } } 

唯一的区别是它返回一个boolean ,并且该消息应该被指定为<o:validateMultiple> message属性。

这里没有提到Apache ExtVal

这里有一些交叉验证(可能有用的其他验证):

https://cwiki.apache.org/confluence/display/EXTVAL/Property+Validation+Usage#PropertyValidationUsage-CrossValidation