如何在 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
,因此它将一直存在到用户会话到期。
一种解决方法是使用<f:event type="preRenderView" listener="bean.init" />
,如下所述:What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?(无需使用<f:metadata>
,如 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 的范围。
【讨论】:
<f:event>
does not necessarily need to go inside <f:metadata>
顺便说一下,OmniFaces 1.6 将附带一个 CDI 兼容 @ViewScoped
用于 JSF 2.0/2.1。
@BalusC 你最后的评论是个好消息。我会等待并尝试它。
这已经在“以上是关于如何在 JSF 页面加载之前在支持 bean 中启动特殊的 init 事件?的主要内容,如果未能解决你的问题,请参考以下文章
JSF 如何从支持 bean 重定向到支持 bean 中动态构建的 URL?
如何在页面加载时处理支持 bean 中的 GET 查询字符串 URL 参数?