【发布时间】:2011-09-27 18:42:11
【问题描述】:
我有以下模板(masterLayout.xhtml):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html">
<ui:insert name="metadata"/>
<h:head>
<title><ui:insert name="windowTitle"/> | MySite</title>
</h:head>
<h:body>
<div id="container">
<div id="header">
<ui:insert name="header">
<ui:include src="/WEB-INF/templates/header.xhtml"/>
</ui:insert>
</div>
<div id="content">
<ui:insert name="content"/>
</div>
<div id="footer">
<ui:insert name="footer">
<ui:include src="/WEB-INF/templates/footer.xhtml"/>
</ui:insert>
</div>
</div>
</h:body>
</f:view>
</html>
以及使用它的页面(search.xhtml):
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title></title>
</h:head>
<h:body>
<ui:composition template="/WEB-INF/templates/masterLayout.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="address" value="#{searchBean.address}"/>
<f:event type="preRenderView" listener="#{userSessionBean.preRenderViewCookieLogin(e)}"/>
<f:event type="preRenderView" listener="#{searchBean.preRenderView(e)}"/>
</f:metadata>
</ui:define>
<ui:define name="windowTitle">#{searchBean.address}</ui:define>
<ui:define name="content">
<!-- Content goes here -->
</ui:define>
</ui:composition>
</h:body>
</html>
问题是我想在模板中调用userSessionBean.preRenderViewCookieLogin(e),因为还有很多其他页面。此方法检查用户是否已登录(根据会话状态),如果没有,则检查可用于登录用户的 cookie 是否可用,如果是(并且如果有效),则自动登录用户.系统在上面的代码中工作,但是当我尝试将其推送到模板中时,不再设置我的视图参数。
这是上面的修改版本,userSessionBean.preRenderViewCookieLogin(e) 被推送到模板中。
masterLayout.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html">
<f:metadata>
<f:event type="preRenderView" listener="#{userSessionBean.preRenderViewCookieLogin(e)}"/>
<ui:insert name="metadata"/>
</f:metadata>
<h:head>
<title><ui:insert name="windowTitle"/> | MySite</title>
</h:head>
<h:body>
<div id="container">
<div id="header">
<ui:insert name="header">
<ui:include src="/WEB-INF/templates/header.xhtml"/>
</ui:insert>
</div>
<div id="content">
<ui:insert name="content"/>
</div>
<div id="footer">
<ui:insert name="footer">
<ui:include src="/WEB-INF/templates/footer.xhtml"/>
</ui:insert>
</div>
</div>
</h:body>
</f:view>
</html>
搜索.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title></title>
</h:head>
<h:body>
<ui:composition template="/WEB-INF/templates/masterLayout.xhtml">
<ui:define name="metadata">
<f:viewParam name="address" value="#{searchBean.address}"/>
<f:event type="preRenderView" listener="#{searchBean.preRenderView(e)}"/>
</ui:define>
<ui:define name="windowTitle">#{searchBean.address}</ui:define>
<ui:define name="content">
<!-- Content goes here -->
</ui:define>
</ui:composition>
</h:body>
</html>
请注意,我已将 <f:metadata/> 标记移至模板。仅此一项就是问题,因为删除 userSessionBean.preRenderViewCookieLogin(e) 没有任何区别。我还尝试了对有效代码的变体,即将userSessionBean.preRenderViewCookieLogin(e) 移动到模板中,这意味着它不能位于<f:metadata/> 标记内。在这种情况下,该方法在所有视图参数都已设置并调用 searchBean.preRenderView(e) 后执行。我希望在调用任何页面的preRenderView(e) 之前调用userSessionBean.preRenderViewCookieLogin(e),而不是之后调用。只是为了好玩,我尝试在userSessionBean.preRenderViewCookieLogin(e) 周围放置一个<f:metadata/>,它调用了这个方法,但没有设置视图参数。
所以,我想知道:
- 为什么会发生这种情况?有办法解决吗?
- 有没有更好的方法来确保每个页面都先调用相同的方法?
编辑:
我只是尝试了其他方法-阶段事件:
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase(e)}">
这是在 masterLayout.xhtml 中。它根本没有被调用;不用于任何阶段。
编辑:
删除了 e(该死的 NetBeans!):
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase}">
这只是在渲染响应阶段之前调用,这当然意味着它是在引发preRenderView 事件之后调用的。
【问题讨论】: