如何在加载JSF页面之前在辅助bean中启动特殊的init事件?

时间:2013-08-28 14:31:04

标签: jsf jsf-2 cdi

PF 3.5.10,Mojarra 2.1.21,Omnifaces 1.5

如何在加载.xhtml JSF页面之前调用特殊的init() - 某些(CDI)SessionScoped bean的方法?现在我调用init(),如果用户从站点菜单中选择页面(使用p:menutitem)。但是,如果用户使用浏览器地址行直接输入url该怎么办?

修改:my.xhtml

<ui:define template="/mytemp.xhtml">
   <f:event type="preRenderView" listener="#{mybean.init()}" />
   <h:form>
     <p:commandButton update="@form" ... />
   </h:form>
</ui:define>

如果我这样做,init()将在每次更新时调用(即在每次回发到服务器时),例如每次单击commandButton时。所以我不能使用你的提议。

编辑2:谢谢Luiggi Mendoza和BalusC! 除了Luiggi Mendoza的解决方案之外,正如评论所述,Omnifaces 1.6也将拥有ViewScope。

1 个答案:

答案 0 :(得分:9)

问题是在创建托管bean并注入字段后调用@PostConstruct public void init()方法。由于您的bean是@SessionScoped,它将一直存在,直到用户会话到期。

解决方法是使用<f:event type="preRenderView" listener="{bean.init}" />,如下所示:What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?(无需使用BalusC在此解释的<f:metadata>Does it matter whether place f:event inside f:metadata or not?)。

根据您的问题更新,此问题在第一个链接中处理。我将发布相关代码来处理这种情况(取自BalusC答案):

public void init() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (!facesContext.isPostback() && !facesContext.isValidationFailed()) {
        // ...
    }
}

如果您迁移到JSF 2.2,那么a @ViewScoped annotation for CDI beans就可以相应地缩小@SessionScoped bean的范围。