JSF不支持跨领域验证,是否有解决方法?

时间:2011-06-08 17:00:53

标签: validation jsf jsf-2

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

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

2 个答案:

答案 0 :(得分:56)

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

E.g。

<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> ,那么相关组件的值已经转换和验证,您应该通过{{3}获取它们}或者UIInput#getValue()(如果UIInput不是UIInput#getLocalValue())。

另见:


或者,您可以使用第三方标签/组件。例如,Validator for multiple fields (JSF 1.2 targeted)有一个RichFaces标记,<rich:graphValidator>有一个Seam3,而<s:validateForm>有几个标准的OmniFaces组件这些都是展示<o:validateXxx>。 OmniFaces使用基于组件的方法,从而在here中完成工作。它也允许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,并且该消息应在message中指定为<o:validateMultiple>属性。

答案 1 :(得分:1)

这里没有提到

Apache ExtVal

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

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