【问题标题】:jsf validate two fields in one time [duplicate]jsf一次验证两个字段[重复]
【发布时间】:2011-03-29 12:48:06
【问题描述】:

我可以用一个验证器验证两个相互依赖的字段吗?

     <h:form>
            <h:inputText value="#{logRegBean.person.name}" >
                <f:validator validatorId="loginCorrectValidator" />
            </h:inputText>
            <h:inputSecret value="#{logRegBean.person.password}" />
            <h:commandButton action="#{logRegBean.login}" />
        </h:form>

我想在数据库中搜索用户,如果有用户,我会测试密码(在数据库中和输入的)是否匹配。但是我如何才能访问一个验证器中的密码字段呢?我试图通过createValueExpression() 评估另一个字段的值,但看起来我在那段时间无法访问该值,因为我总是得到空字符串。

【问题讨论】:

    标签: validation jsf


    【解决方案1】:

    你能做的最好的事情是通过UIViewRoot#findComponent()validate() 方法中获取另一个UIInput 组件,然后通过UIInput#getSubmittedValue() 确定提交的值(当它发生时之后组件树中当前经过验证的组件)或UIInput#getValue()(当它出现在当前组件之前,因此已经经过验证)。

    例如

    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        UIInput otherInput = (UIInput) context.getViewRoot().findComponent("clientId");
        String otherValue = (String) otherInput.getSubmittedValue();
        // ...
    }
    

    另见:

    【讨论】:

    • 我也有同样的问题。我在我的代码中添加了示例代码。但是我得到了空指针异常。你能告诉我为什么吗?
    • @Kayser:通常,当代码尝试访问/调用实际上是null 的引用时,您会得到它。另见docs.oracle.com/javase/7/docs/api/java/lang/…
    • DateIntervalValidator 不能为空 public void validate(FacesContext context, UIComponent component, Object value) { UIInput fromComponent = (UIInput) context.getViewRoot().findComponent("from"); Date fromDate = (Date) fromComponent.getSubmittedValue(); &lt;rich:calendar id="from"&gt; &lt;f:validator binding="#{dateFieldValidator}"/&gt; &lt;f:attribute name="fromDate" value="#{msg['from']}"/&gt; &lt;/rich:calendar&gt; &lt;rich:calendar id="until"&gt; &lt;f:validator binding="#{dateFieldValidator}" /&gt; &lt;f:validator binding="#{dateIntervalValidator}"/&gt; &lt;f:attribute name="untilDate" value="#{msg['until']}"/&gt; &lt;/rich:calendar&gt;
    • @Kayser try findComponent(":from") 其中 是表单的实际 ID(省略角括号)。不要吃肉。
    • 请注意,对于绝对 ID,您需要在 UIViewRoot#findComponent() 中的 ID 之前添加一个 :。我认为,根据文档,它似乎遵循与 XHTML ID 搜索相同的规则。
    【解决方案2】:

    我认为 SeamFaces 的 s:validateForm feature 可能正是您所需要的。 (Seam Faces 是一个非常有用的库,它为 JSF 带来了一些基于 CDI 的漂亮特性。)

    【讨论】:

    • 任何人都可以提供或链接有关在 Seam 停止并将验证转移到 beanvalidation.org 后s:validateForm 可用的位置的信息 [seamframework.org/Seam3]
    • @KarlRichter 据我所知,Seam 的继任者 Apache DeltaSpike 中还没有表单验证。目前,您仍然可以使用 Seam 的 s:validateForm 或 RichFaces 的 rich:graphValidator
    【解决方案3】:

    JSF 中的验证机制旨在验证单个组件。
    但是,在实践中,您通常需要确保相关组件具有合理的值,然后才能将值传播到模型中。
    例如,要求用户在单个文本字段中输入日期不是一个好主意。
    相反,您将使用三个不同的文本字段,分别表示日、月和年。

    如果用户输入了非法日期,例如 2 月 30 日,您希望显示验证错误并防止非法数据进入模型。

    诀窍是将验证器附加到最后一个组件。当它的验证器被调用时,前面的组件通过了验证并设置了它们的本地值。最后一个组件已通过转换,转换后的值作为验证方法的Object参数传递。

    当然,您需要能够访问其他组件。您可以通过使用包含当前表单的所有组件的支持 bean 轻松实现该访问。只需将验证方法附加到支持 bean:

    public class BackingBean {
    
        private int day;
        private int month;
        private int year;
    
        private UIInput dayInput;
        private UIInput monthInput;
        private UIInput yearInput;
    
        // PROPERTY: day
        public int getDay() { return day; }
        public void setDay(int newValue) { day = newValue; }
    
        // PROPERTY: month
        public int getMonth() { return month; }
        public void setMonth(int newValue) { month = newValue; }
    
        // PROPERTY: year
        public int getYear() { return year; }
        public void setYear(int newValue) { year = newValue; }
    
        // PROPERTY: dayInput
        public UIInput getDayInput() { return dayInput; }
        public void setDayInput(UIInput newValue) { dayInput = newValue; }
    
        // PROPERTY: monthInput
        public UIInput getMonthInput() { return monthInput; }
        public void setMonthInput(UIInput newValue) { monthInput = newValue; }
    
        // PROPERTY: yearInput
        public UIInput getYearInput() { return yearInput; }
        public void setYearInput(UIInput newValue) { yearInput = newValue; }
    
        public void validateDate(FacesContext context, UIComponent component, Object value) {
    
           int d = ((Integer) dayInput.getLocalValue()).intValue();
           int m = ((Integer) monthInput.getLocalValue()).intValue();
           int y = ((Integer) value).intValue();
    
           if (!isValidDate(d, m, y)) {
              throw new ValidatorException(new FacesMessage("Invalid Date"));
           }
    
        }
    
        private static boolean isValidDate(int d, int m, int y) {
            //DO YOUR VALIDATION HERE
        }
    
     }
    

    这是您的 JSP

     <html>
    
       <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
       <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    
        <f:view>
    
           <head></head>
    
           <body>
    
              <h:form>
    
                 <h:panelGrid columns="3">
    
                    <h:inputText value="#{bb.day}"   binding="#{bb.dayInput}" size="2" required="true"/>
    
                    <h:inputText value="#{bb.month}" binding="#{bb.monthInput}" size="2" required="true"/>
    
                    <h:inputText value="#{bb.year}"  binding="#{bb.yearInput}" size="4" required="true" validator="#{bb.validateDate}"/>
    
                    <h:message for="year" styleClass="errorMessage"/>
    
                 </h:panelGrid>
    
                 <h:commandButton value="Submit" action="submit"/>
    
              </h:form>
    
           </body>
    
        </f:view>
    
     </html>
    

    参考: 核心 JavaServer™ 面孔 大卫·盖瑞,凯·霍斯曼

    出版商:Addison Wesley 发布日期:2004 年 6 月 15 日 国际标准书号:0-13-146305-5

    【讨论】:

    • 如果您输入了一个有效的日期,例如 2017 年 2 月 28 日,然后将日期更改为 30 日,会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    相关资源
    最近更新 更多