使用 ExternalContext.redirect() 向重定向页面添加人脸消息 [英] Adding faces message to redirected page using ExternalContext.redirect()

查看:17
本文介绍了使用 ExternalContext.redirect() 向重定向页面添加人脸消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ExternalContext.redirect(String); 方法将用户重定向到另一个页面:

I am using ExternalContext.redirect(String); method to redirect user to another page:

FacesContext.getCurrentInstance().addMessage(new FacesMessage("Bla bla bla..."));
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/scenario.xhtml");

正如 Matt Handy 在他的回答中提到的,我使用了 Flash.setKeepMessages(true); 但它似乎不适用于 ExternalContext.redirect.(尽管当我通过从 bean 的操作方法返回页面名称进行重定向时它可以工作.)

As Matt Handy mentioned in his answer, I used Flash.setKeepMessages(true); but it does not seem to work with ExternalContext.redirect. (Although it works when I redirect by returning a page name from bean's action method.)

现在如何添加 FacesMessage 以使其在重定向的 (scenario.xhtml) 页面中可见?

Now how can I add FacesMessage so that it is visible in the redirected (scenario.xhtml) page?

推荐答案

这似乎是一个时间问题.在 preRenderView 事件期间调用此侦听器方法.根据ELFlash的源码(Mojarra的FlashExternalContext#getFlash() 返回的实现)事实证明,当您当前坐着时,它不会设置 flash cookie在呈现响应阶段并且尚未为当前请求设置 flash cookie:

This seems to be a timing problem. This listener method is invoked during the preRenderView event. According to the source code of ELFlash (Mojarra's Flash implementation as returned by ExternalContext#getFlash()) it turns out that it won't set the flash cookie when you're currently sitting in the render response phase and the flash cookie hasn't been set yet for the current request:

以下是来自 ELFlash 的相关行:

Here are the relevant lines from ELFlash:

if (currentPhase.getOrdinal() < PhaseId.RENDER_RESPONSE.getOrdinal()) {
    flashInfo = flashManager.getPreviousRequestFlashInfo();
} else {
    flashInfo = flashManager.getNextRequestFlashInfo(this, true);
    maybeWriteCookie(context, flashManager);
}

maybeWriteCookie 只会在 Flash cookie 需要第二次通过时(即当重定向页面又重定向到另一个页面时)设置 cookie.

The maybeWriteCookie would only set the cookie when the flash cookie needs to be passed through for the second time (i.e. when the redirected page in turn redirects to another page).

这是一个不幸的角落案例.这个 ELFlash 逻辑是有道理的,但这并不是你真正想要的.基本上您需要在 INVOKE_APPLICATION 阶段添加消息.然而,没有像 postInvokeAction 这样的事件.使用新的 JSF 2.2 <f:viewAction> 标记,它应该是可能的,因为它确实在调用应用程序阶段运行.

This is an unfortunate corner case. This ELFlash logic makes sense, but this isn't what you actually want. Basically you need to add the message during INVOKE_APPLICATION phase instead. There is however no such event as postInvokeAction. With the new JSF 2.2 <f:viewAction> tag it should be possible as it really runs during invoke application phase.

<f:viewAction action="#{bean.onload}" />

只要您还没有使用 JSF 2.2,您就需要寻找替代方法.最简单的方法是创建一个自定义的 ComponentSystemEvent.

As long as you're not on JSF 2.2 yet, you'd need to look for alternate ways. The easiest way would be to create a custom ComponentSystemEvent.

@NamedEvent(shortName="postInvokeAction")
public class PostInvokeActionEvent extends ComponentSystemEvent {

    public PostInvokeActionEvent(UIComponent component) {
        super(component);
    }

}

现在你需要一个钩子来发布这个事件.最明智的地方是一个PhaseListenerINVOKE_APPLICATION 阶段之后监听.

Now you need somewhere a hook to publish this event. The most sensible place is a PhaseListener listening on after phase of INVOKE_APPLICATION.

public class PostInvokeActionListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.INVOKE_APPLICATION;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // NOOP.
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot());
    }

}

如果在faces-config.xml

<lifecycle>
    <phase-listener>com.example.PostInvokeActionListener</phase-listener>
</lifecycle>

然后您就可以按如下方式使用新事件

then you'll be able to use the new event as follows

<f:event type="postInvokeAction" listener="#{bean.onload}" />

<小时>

更新 JSF 实用程序库 OmniFaces 中也提供了此功能,因此您无需需要自制一个和另一个.另请参阅 InvokeActionEventListener 展示示例.


Update this is also available in the JSF utility library OmniFaces, so you don't need to homebrew the one and other. See also the InvokeActionEventListener showcase example.

这篇关于使用 ExternalContext.redirect() 向重定向页面添加人脸消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆