如何在 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 事件?的主要内容,如果未能解决你的问题,请参考以下文章

JSF 如何从支持 bean 重定向到支持 bean 中动态构建的 URL?

java jsf 如何去重新加载bean

如何在页面加载时处理支持 bean 中的 GET 查询字符串 URL 参数?

在页面加载时调用 JSF 托管 bean 操作

如何在 JSF 的支持 bean 中获取 Unicode 数据

h:commandButton 不能与 JSF bean 一起工作,而页面正在加载