jsf一次验证两个字段[重复]

Posted

技术标签:

【中文标题】jsf一次验证两个字段[重复]【英文标题】:jsf validate two fields in one time [duplicate] 【发布时间】: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() 评估另一个字段的值,但看起来我在那段时间无法访问该值,因为我总是得到空字符串。

【问题讨论】:

【参考方案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();
    // ...

另见:

JSF doesn't support cross-field validation, is there a workaround?

【讨论】:

我也有同样的问题。我在我的代码中添加了示例代码。但是我得到了空指针异常。你能告诉我为什么吗? @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 日,会发生什么?

以上是关于jsf一次验证两个字段[重复]的主要内容,如果未能解决你的问题,请参考以下文章

jsf(richfaces)只读输入文本验证[重复]

必填字段的 JSF 验证

JSF 不支持跨字段验证,有解决方法吗?

JSF 2.1 条件字段验证

使用 JSR 303 在 JSF 中使用内联消息进行跨字段验证

如何从 JSF/ADF 验证器中获取旧值?