我有以下模板(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>
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: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/>
标签,它调用了这个方法,但没有设置视图参数。因此,我想知道:
1.为什么会发生这种情况,有没有办法解决?
2.有没有更好的方法来确保相同的方法在任何其他操作之前被调用?
编辑: 我刚才尝试了另外一件事 - 一个阶段事件:
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase(e)}">
这是在masterLayout.xhtml中。它根本没有被调用;不为任何阶段。
编辑:
删除了e
(该死的NetBeans!):
<f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase}">
这仅在渲染响应阶段之前被调用,这当然意味着它在引发preRenderView
事件之后被调用。
preRenderView
之前调用相同的方法吗? - Steve(e)
。在作用域中没有这样的东西。 - BalusCuserSessionBean
(会话作用域),然后调用该bean上执行cookie登录的方法。我在这里使用并点赞了您的一些代码here,以便在阶段监听器中按名称获取bean。我很快就会在这里发布解决方案。 - Steve