jsf2-jsf 2-View参数验证和重定向



我们使用JSF 2+Primefaces+Glassfish+CDI/WELD进行开发。我们在search.xhtml页面上有一个图书列表的datalist/dataTable,每个列表都呈现为outputLink。单击任何条目,就会显示view.xhtml以及所有书籍详细信息。这是我们的search.xhtml中被调用的代码:

<h:outputLink value="${request.contextPath}/viewBook.xhtml?id=${book.id}">${book.title} 
</h:outputLink> 

在viewBook.xhtml中,根据URL中传递的图书Id,在呈现页面之前填充详细信息,如下所示:

<f:metadata>
    <f:viewParam name="id" value="#{bookBean.id}"/>     
        </f:viewParam>
    <f:event type="preRenderView" listener="#{bookBean.populate}" />
</f:metadata>

我们的要求是在呈现页面之前验证Id,如果数据库中不存在,我们需要将其重定向到错误页面或在同一页面上显示错误消息,即搜索页面

我们尝试以两种不同的方式验证图书Id:1.在填充方法中使用验证,如下

if (bookFound)
{
    //Display details
}
else
{
    FacesContext fc = FacesContext.getCurrentInstance();
    fc.addMessage("id", new FacesMessage("No such book found in the system. Please try again."));
    fc.renderResponse();
}
  1. 通过在view.xhtml中挂接一个自定义验证器,并在屏幕上抛出一个验证器异常(Faces消息)。我们使用CDI-WELD,所以我们可以使用注入。

    <f:metadata>
        <f:viewParam name="id" value="#{bookBean.id}"/>
       <f:validator validatorId="bookIdValidator"/>
        </f:viewParam>
        <f:event type="preRenderView" listener="#{bookBean.populate}" />
    </f:metadata>
    

这两种方法都有效,但它们在视图屏幕上显示错误,而不是在搜索屏幕上。可以使用以下代码将其重定向到错误页面:

FacesContext.getCurrentInstance().getExternalContext().redirect("/error.xhtml");
  1. 是否有一种方法可以处理验证,以便在单击outputLink的搜索页面上显示错误消息。我们知道我们需要在搜索页面上处理验证,但如何将验证器与h:outputLink相关联。我们可以使用h:link吗?(我们需要使用GET请求,而不是POST。所以使用commandLink或Button是不可行的)
  2. 有没有比我们现在这样做更好的方法重定向到错误页面?

    (FacesContext.getCurrentInstance().getExternalContext().redirect("/error.xhtml");)

任何建议都将不胜感激。

感谢和问候

gkari,

你能使用JSF进行导航吗?我不熟悉WELD,但纯JSF解决方案可能如下所示。这假设您有一个名为bookBean的backingbean。它应该有一个名为id的属性,带有getter(getId)和setter(setId)。

  1. 在您的backingbean中创建一个空白方法。它必须不接受任何参数并返回一个String。

    String viewBook() {
        // We'll fill this in later.
        return "success";
    }
    
  2. h:outputLink更改为h:commandLink,这将调用新方法:

    <h:commandLink action="#{bookBean.viewBook}" />
    
  3. 当链接被激活时,使用设置bookBean的id属性的操作更新链接:

    <h:commandLink action="#{bookBean.viewBook}">
        <f:setPropertyActionListener
            target="#{bookBean.id}"
            value="#{book.id}" />
    </h:commandLink>
    
  4. 更新backingbean中的新方法以进行所需的验证,并返回一个指示成功或失败的字符串:

    String viewBook() {
        String result;
        if (bookIdIsValid (this.getId()) {
            result = "success";
        } else {
            result = "error";
        }
        return result;
    }
    
  5. 在faces-config.xml中创建导航规则,以路由到正确的目标,具体取决于结果代码:

    <navigation-rule>
        <from-view-id>/search.xhtml</from-view-id>
        <navigation-case>
            <from-action>#{bookBean.viewBook}</from-action>
            <from-outcome>success</from-outcome>
            <to-view-id>/viewBook.xhtml</to-view-id>
        </navigation-case>
        <navigation-case>
            <from-action>#{bookBean.viewBook}</from-action>
            <from-outcome>error</from-outcome>
            <to-view-id>/error.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>
    

这允许backingbean将结果指示给JSF,JSF库将处理重定向到适当的位置。

听起来你遇到的问题是,你在一个页面上创建了FacesMessage,但却想在另一个页面显示它。你需要将FacesMessage隐藏到用户会话中(或者可能是一个更短的范围,如果可用的话),然后在你想要显示它的页面上将其取出。

有一些自动化的尝试:

JSF 2中有一个Flash作用域和一个方法setKeepMessages。你可以试试这个,但我运气不太好。

这里讨论了复制和粘贴阶段侦听器解决方案:http://ocpsoft.com/java/persist-and-pass-facesmessages-over-page-redirects/

跨重定向显示消息也是Seam 3的一个特性。

最新更新