Events JSF f:模板f:元数据中的事件preRenderView,在每次访问页面时都不会调用侦听器

Events JSF f:模板f:元数据中的事件preRenderView,在每次访问页面时都不会调用侦听器,events,jsf,jsf-2,prerender,Events,Jsf,Jsf 2,Prerender,Mojarra-2.1.3符合Glassfish 3.1.1(与Netbeans7.1一起分发) 我有一个@SessionScoped支持bean跟踪器,带有一个侦听器void reset() 以下内容在使用template.XHTML的所有XHTML页面的f:metadata中都可以正常工作,例如/block/view.XHTML,它还接受一个查询参数id: <f:view> <f:metadata> <f:viewParam name="

Mojarra-2.1.3符合Glassfish 3.1.1(与Netbeans7.1一起分发)

我有一个@SessionScoped支持bean跟踪器,带有一个侦听器void reset()

以下内容在使用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中。但当我这么做的时候,奇怪的事情发生了。在第一次加载/block/view.xhtml时,它只调用了一次#{tracker.reset}(无论id查询参数是什么),此后,直到我加载了另一个具有不同viewId的页面,如/actor/view.xhtml或/block/list.xhtml或/index.html,它才被再次调用

我在template.xhtml中使用#{facesContext.viewRoot.viewId}检查了viewId。从viewId的角度来看,很明显,查询参数id在区分不同的块/视图方面不起作用。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:元数据中放置f:事件与否会有区别

我问这个问题的原因是这里有很多关于Stackoverflow的例子,在template.xhtml中使用f:metadata,在template.xhtml中的f:metadata中使用f:event

BalusC说:

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

只有在最终XHTML页面的f:metadata中有preRenderView f:event,或者在模板的f:metadata之外,但不在模板的f:metadata之内时,这似乎才是正确的(按预期工作)

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

JSF2完整参考(Burns和Schalk)第540页规定:

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

但是有很多关于f:metadata在模板中使用的Stackoverflow的例子,也有很多f:metadata中使用的f:event的例子。这里也讨论了这一点:

BalusC对此进行了有益的解释:

。。不严格要求将容器放置在内部。它可以连接到任何组件。。它确实是为了纯粹的自我记录的目的,当你有一堆s并且想在所有这些视图参数都设置好之后钩住a来调用一个动作的时候,就放在里面

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

本身只能在模板客户端中使用,不能在主模板中使用。也就是说,它必须在您通过URL实际请求的页面中声明,而不是在
后面的页面中声明,否则它将被忽略。此特定限制与
无关

另见:

感谢您的回复,我已经从我的模板中删除了f:metadata,在h:head之前完全保留了f:event项,现在它们可以正常工作了。如果在模板中错误地将f:事件放置在不允许的f:元数据中(我最初的问题,但不再相关,因为这是f:元数据的病态用法),那么为什么会发生这种奇怪的行为就不再重要了,因此我将接受这一完整的答案。