0

我对 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>

支持豆:

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 中保存的消息消失了。知道为什么要删除闪存范围或其他方式吗?

消息.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>
4

1 回答 1

4

<f:event type="preRenderView">设置 Flash 范围属性为时已晚。当 JSF 当前处于渲染响应阶段时,无法创建 flash 范围。您基本上需要在渲染响应阶段之前设置 flash 作用域属性。尽管 name preRenderView,这个事件实际上是在渲染响应阶段(最开始)期间触发的。

您基本上需要在 INVOKE_ACTION 阶段调用侦听器方法。由于没有标准<f:event>类型,因此您需要自行开发。此答案中对此进行了详细概述:Can't keep faces message after navigation from preRender

您最终希望成为:

<f:event listener="#{signupMaterialBean.initFromContext()}"
         type="postInvokeAction" />

请注意,此事件已由OmniFaces提供。另请参阅处理此问题InvokeActionEventListener展示页面。


与具体问题无关NullPointerException,流行的是巨大的代码气味。不要捕获这样的运行时异常。通过执行空检查等来防止它们if (foo != null)。那些空洞的东西IOException也很糟糕。将它们全部删除,然后添加throws IOException到方法中。

此外,重定向路径问题自 Mojarra 2.1.14 起已修复。因此,自从该版本以来,您可以安全地重定向到不同的基本路径。

于 2012-11-22T14:06:50.400 回答