我们使用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();
}
通过在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");
- 是否有一种方法可以处理验证,以便在单击outputLink的搜索页面上显示错误消息。我们知道我们需要在搜索页面上处理验证,但如何将验证器与h:outputLink相关联。我们可以使用h:link吗?(我们需要使用GET请求,而不是POST。所以使用commandLink或Button是不可行的)
有没有比我们现在这样做更好的方法重定向到错误页面?
(FacesContext.getCurrentInstance().getExternalContext().redirect("/error.xhtml");)
任何建议都将不胜感激。
感谢和问候
gkari,
你能使用JSF进行导航吗?我不熟悉WELD,但纯JSF解决方案可能如下所示。这假设您有一个名为bookBean的backingbean。它应该有一个名为id
的属性,带有getter(getId
)和setter(setId
)。
-
在您的backingbean中创建一个空白方法。它必须不接受任何参数并返回一个String。
String viewBook() { // We'll fill this in later. return "success"; }
-
将
h:outputLink
更改为h:commandLink
,这将调用新方法:<h:commandLink action="#{bookBean.viewBook}" />
-
当链接被激活时,使用设置bookBean的
id
属性的操作更新链接:<h:commandLink action="#{bookBean.viewBook}"> <f:setPropertyActionListener target="#{bookBean.id}" value="#{book.id}" /> </h:commandLink>
-
更新backingbean中的新方法以进行所需的验证,并返回一个指示成功或失败的字符串:
String viewBook() { String result; if (bookIdIsValid (this.getId()) { result = "success"; } else { result = "error"; } return result; }
-
在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的一个特性。