3

根据 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:events 进行分组)。这适用于 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 在何时使用 f:viewAction / preRenderView 与 PostConstruct 中声明?

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

如果我在最终 XHTML 页面的 f:metadata 或模板的 f:metadata 之外,但不在 f:metadata 的 f:metadata 中,这似乎是正确的(按预期工作)模板。

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

JSF2 Complete Reference (Burns and Schalk) p.540 状态:

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

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

是否将 f:event 放在 f:metadata 中是否重要?

BalusC 帮助解释的地方:

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

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

4

1 回答 1

10

The <f:metadata> itself can only be used in the template client, not in the master template. I.e. it has to be declared in the page which you're actually requesting by URL, not inside the page behind <ui:composition template>, it will otherwise just be ignored. This particular restriction is unrelated to the <f:event>.

See also:

于 2012-06-17T13:26:57.270 回答