我在使用JSF的FlashScope时遇到问题,请注意我知道重定向应指向与调用页面相同的基本路径。
我的情况是,当客户端点击他/她的电子邮件中的链接时,该操作将被初始化,然后它将加载带有支持bean的.xhtml(具有preRenderView事件)页面以检查传递的参数。当参数错误时,它必须重定向到带有消息的新页面。
观点:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:metadata>
<f:viewParam name="dummy" />
<f:event listener="#{signupMaterialBean.initFromContext()}"
type="preRenderView"></f:event>
</f:metadata>
<h:outputText value="#{signupMaterialBean.html}" escape="false"></h:outputText>
</ui:composition>
支持Bean:
public void initFromContext() {
try {
Map<String, String> params = facesContext.getExternalContext()
.getRequestParameterMap();
...
} catch (NullPointerException e) {
try {
Message message = new Message();
String msg = "Invalid parameters";
message.setMessage(msg);
JSFUtils.flashScope().put("message", message);
facesContext.getExternalContext().redirect("message.xhtml");
facesContext.responseComplete();
} catch (IOException ioe) {
}
} catch (IOException e) {
}
}
重定向有效,但FlashScope中的消息保存消失了。知道闪存范围被删除的原因或其他方法吗?
message.xhtml
<ui:define name="head"></ui:define>
<ui:define name="content">
<div class="box-middle-content faded">
<div class="message">
<h:outputText escape="false" value="#{flash.message.message}"></h:outputText>
<br />
<p>
<h:outputText value="#{msgs['message.footer']}" escape="false" />
</p>
</div>
</div>
</ui:define>
</ui:composition>
JSFUtils
public class JSFUtils {
public static Flash flashScope() {
return (FacesContext.getCurrentInstance().getExternalContext()
.getFlash());
}
}
更新了视图:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<f:metadata>
<f:viewParam name="dummy"></f:viewParam>
<f:event type="postInvokeAction"
listener="#{signupMaterialBean.initFromContext}" />
</f:metadata>
<h:outputText value="#{signupMaterialBean.html}" escape="false"></h:outputText>
</ui:composition>
答案 0 :(得分:4)
<f:event type="preRenderView">
设置闪存范围属性为时已晚。当JSF当前处于渲染响应阶段时,无法创建闪存范围。您基本上需要在渲染响应阶段之前设置闪存范围属性。尽管名称为preRenderView
,但此事件实际上是在(渲染响应阶段的最开始)期间触发的。
您基本上需要在INVOKE_ACTION阶段调用侦听器方法。因为没有标准的<f:event>
类型,所以你需要自己生成一个。在这个答案中详细概述了这一点:Can't keep faces message after navigation from preRender。
你最终想结束:
<f:event listener="#{signupMaterialBean.initFromContext()}"
type="postInvokeAction" />
请注意,此事件已由OmniFaces提供。另请参阅the InvokeActionEventListener
showcase page来处理这个问题。
无关,NullPointerException
上的捕获是一个巨大的代码味道。不要捕获这样的运行时异常。通过执行if (foo != null)
等空值检查来阻止它们。此外IOException
上的那些空捕获也非常糟糕。将它们全部删除,只需将throws IOException
添加到方法中即可。
此外,自Mojarra 2.1.14以来,重定向路径问题已得到修复。因此,从该版本开始,您可以安全地重定向到不同的基本路径。