【问题标题】:JSF f:event preRenderView in template f:metadata, listener not being called on every page access模板 f:metadata 中的 JSF f:event preRenderView,没有在每次页面访问时调用监听器
【发布时间】:2012-06-19 15:12:56
【问题描述】:

按照 Glassfish3.1.1 的 Mojarra-2.1.3(随 Netbeans7.1 分发)

我有一个带有监听器 void reset() 的 @SessionScoped 后备 bean Tracker。

以下内容在所有使用 template.xhtml 的 XHTML 页面的 f:metadata 中都可以正常工作,例如 /block/view.xhtml,它也采用查询参数 id:

<f:view>
    <f:metadata>
        <f:viewParam name="id" value="#{blockManager.id}"/>
        <f:event type="preRenderView" listener="#{tracker.reset}"/>            
    </f:metadata>
</f:view>

<ui:composition template="/template.xhtml">

正如预期的那样,每当我加载 (GET) 或重新加载页面时,无论 id 查询参数是什么,都会调用 #{tracker.reset} 侦听器(如调试日志所示)。

但是,必须在每个 XHTML 页面(其中有数百个页面)中包含 f:event 是很乏味的,我首先尝试将它包含在我的 template.xhtml 的 f:metadata 中。但是当我做一些奇怪的事情时发生了。它只调用了一次#{tracker.reset},第一次加载/block/view.xhtml(无论id查询参数是什么),之后它才被再次调用,直到我加载另一个具有不同viewId的页面,例如 /actor/view.xhtml,或 /block/list.xhtml,或 /index.html。

我在 template.xhtml 中使用 #{facesContext.viewRoot.viewId} 检查了 viewId。从viewId的角度看很清楚,查询参数id对于区分不同的block/view.xhtml?id=[id]页面没有任何作用,调用不同的id查询参数,viewId永远只是'/block /view.xhtml'。

在撰写此 stackoverflow 帖子期间,我发现了问题的解决方案:只需将 f:event 放在 template.xhtml 的 f:metadata 之外(我在 template.xhtml 中使用 f:metadata 进行分组f:事件)。这适用于 template.xhtml:

<f:metadata>
..
</f:metadata>
<f:event type="preRenderView" listener="#{tracker.reset}"/>
<h:head>

但我还有以下问题:

问:为什么在模板的 f:metadata 中放置 f:event 会有所不同?

我问的原因是 Stackoverflow 上有很多示例,包括在 template.xhtml 中使用 f:metadata 以及在模板中使用 f:metadata 中的 f:event。

BalusC 状态为When to use f:viewAction / preRenderView versus PostConstruct?:

每个 HTTP 请求都会调用 preRenderView 事件。

如果我在最终 XHTML 页面的 f:metadata 中或在模板的 f:metadata 之外但不在 f:模板的元数据。

关于是否应该在模板的 f:metadata 中包含 f:event 或在模板中使用 f:metadata 似乎存在一些争论。

JSF2 完整参考(Burns 和 Schalk)第 540 页指出:

f:metadata 标记封装了一组元素,用于指定 Facelets 视图的元数据,因此必须是 f:view 标记的子级,并且不能出现在模板中。从 JSF2.0 开始,这个标签的唯一目的就是封装 f:viewParam 标签。

但是在 Stackoverflow 上有很多 f:metadata 在模板中使用的示例,并且有很多 f:event 在 f:metadata 中使用的示例。这里也有讨论:

Does it matter whether place f:event inside f:metadata or not?

BalusC 有帮助的解释:

.. 并不严格要求放在 中。它可以连接到任何组件。 .. 当你有一堆 并且想要挂钩 以在所有这些视图参数之后调用一个动作时,它确实是为了纯粹的自我记录目的放在 中已设置。 ..

但我上面的经验表明,将 f:event 放在模板的 f:metadata 中会产生略微不同(奇怪)的行为。为什么?

【问题讨论】:

    标签: events jsf jsf-2 prerender


    【解决方案1】:

    &lt;f:metadata&gt; 本身只能在模板客户端中使用,不能在主模板中使用。 IE。它必须在您实际通过 URL 请求的页面中声明,而不是在 &lt;ui:composition template&gt; 后面的页面中声明,否则它将被忽略。此特定限制与&lt;f:event&gt; 无关。

    另见:

    【讨论】:

    • 感谢您的回复,我已经从模板中删除了 f:metadata,在 h:head 之前完全保留了 f:event 项目,现在它们可以正常工作了。如果一个人错误地将 f:event 放置在模板中不允许的 f:metadata 中,为什么会发生奇怪的行为不再重要(我最初的问题,但不再相关,因为它是 f:metadata 的病态使用),所以我会接受这个作为完全回答。
    猜你喜欢
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多