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

Posted

技术标签:

【中文标题】如何在 JSF 页面加载之前在支持 bean 中启动特殊的 init 事件?【英文标题】:How to start special init event in a backing bean before JSF page loads? 【发布时间】:2013-08-31 16:48:17 【问题描述】:

PF 3.5.10、Mojarra 2.1.21、Omnifaces 1.5

如何在加载 .xhtml JSF 页面之前调用某些 (CDI)SessionScoped bean 的特殊 init() 方法?如果用户从站点菜单中选择页面(使用p:menutitem),现在我调用 init()。但是如果用户使用浏览器地址行直接输入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() 将在每次更新时调用(即每次回发到服务器时),例如每次单击命令按钮时。所以我不能使用你的提议。

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

【问题讨论】:

【参考方案1】:

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

一种解决方法是使用&lt;f:event type="preRenderView" listener="bean.init" /&gt;,如下所述:What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?(无需使用&lt;f:metadata&gt;,如 BalusC 所述: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 的范围。

【讨论】:

&lt;f:event&gt; does not necessarily need to go inside &lt;f:metadata&gt; 顺便说一下,OmniFaces 1.6 将附带一个 CDI 兼容 @ViewScoped 用于 JSF 2.0/2.1。 @BalusC 你最后的评论是个好消息。我会等待并尝试它。 这已经在“ 可以用来做什么?”中得到回答/解释。链接:) @BalusC 好的,我明白了。我应该在 init() 中进行回发检查。我会试试的。

以上是关于如何在 JSF 页面加载之前在支持 bean 中启动特殊的 init 事件?的主要内容,如果未能解决你的问题,请参考以下文章