1

在我的页面的 preRender 代码中,我添加了 faces 消息,然后导航到另一个页面,如下所示:

if(error){
addMessageToComponent(null,"AN ERROR HAS OCCURRED");
FacesContext.getCurrentInstance().getExternalContext().getFlash()
                .setKeepMessages(true);
navigateActionListener("myoutcome");
}

添加消息和导航的 util 方法是:

public static String getClientId(String componentId)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        UIViewRoot root = context.getViewRoot();

        UIComponent c = findComponent(root, componentId);
        return c.getClientId(context);
    }

    public static UIComponent findComponent(UIComponent c, String id)
    {
        if (id.equals(c.getId())) { return c; }
        Iterator<UIComponent> kids = c.getFacetsAndChildren();
        while (kids.hasNext())
        {
            UIComponent found = findComponent(kids.next(), id);
            if (found != null) { return found; }
        }
        return null;
    }

    /**
     * @param componentId
     *            : the id for the jsf/primefaces component without formId:
     *            prefix. <br>
     *            if you use null then the message will be added to the
     *            h:messages component.
     **/
    public static void addMessageToComponent(String componentId, String message)
    {

        if (componentId != null)
            componentId = GeneralUtils.getClientId(componentId);
        FacesContext.getCurrentInstance().addMessage(componentId,
                new FacesMessage(message));
    }

public static void navigateActionListener(String outcome)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        NavigationHandler navigator = context.getApplication()
                .getNavigationHandler();
        navigator.handleNavigation(context, null, outcome);
    }

但消息未保存,因此重定向后不会出现。

请告知如何解决。

4

1 回答 1

4

preRenderView事件在RENDER_RESPONSE阶段的最开始运行。指示范围保留消息为时已晚。Flash您最迟可以在该INVOKE_APPLICATION阶段执行此操作。

由于对此没有标准的 JSF 组件系统事件,因此您需要自制一个:

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

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

}

要发布此内容,您需要PhaseListener

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>

您将能够按如下方式使用新事件:

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

您只需要确保您至少有一个<f:viewParam>,否则 JSF 根本不会进入调用阶段。

JSF 实用程序库OmniFaces已经支持此事件和preInvokeAction开箱即用的事件。另请参阅展示页面,该页面还演示了为重定向设置面部消息。

于 2012-10-30T17:50:31.480 回答