JSF 2 facelets< f:metadata/>在模板和页面中 [英] JSF 2 facelets <f:metadata/> in template and page

查看:69
本文介绍了JSF 2 facelets< f:metadata/>在模板和页面中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下模板(masterLayout.xhtml):

I have the following template (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):

and page that uses it (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,如果可以,则自动登录用户(如果有效). .系统可以在上面的代码中运行,但是当我尝试将其推入模板时,不再设置我的视图参数.

The problem is that I want to place the call to userSessionBean.preRenderViewCookieLogin(e) in the template because there are many other pages. This method checks that the user is logged in (according to session state) and, if not, checks that a cookie is available which can be used to log the user in and, if so (and if valid), logs the user in automatically. The system works in the code above, but when I try to push this into the template, my view parameters are no longer being set.

这是上面的修改版,其中userSessionBean.preRenderViewCookieLogin(e)上推到模板上.

Here's the modified version of the above, with userSessionBean.preRenderViewCookieLogin(e) pushed up to the template.

masterLayout.xhtml:

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

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/>,它调用了此方法,但是没有设置视图参数.

Notice that I've moved the <f:metadata/> tag to the template. That alone is the problem as removing userSessionBean.preRenderViewCookieLogin(e) makes no difference. I also tried a variation on the code that worked, which was to just move userSessionBean.preRenderViewCookieLogin(e) into the template which means it can't be inside the <f:metadata/> tag. In this case, that method executed after all the view parameters had been set and searchBean.preRenderView(e) called. I want userSessionBean.preRenderViewCookieLogin(e) to be called before any page's preRenderView(e) is called, not after. And just for fun I tried putting an <f:metadata/> around userSessionBean.preRenderViewCookieLogin(e), which called this method, but didn't set the view parameters.

所以,我想知道:

  1. 为什么会这样,有没有办法解决?
  2. 是否有更好的方法来确保在其他任何页面之前都对每个页面调用相同的方法?

修改: 我只是尝试了其他东西-阶段事件: <f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase(e)}"> 这是在masterLayout.xhtml中.它根本没有被调用;没有任何阶段.

I just tried something else - a phase event: <f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase(e)}"> This is in masterLayout.xhtml. It is not being called at all; not for any phase.

修改: 删除了e(该死的NetBeans!): <f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase}"> 这仅在渲染响应阶段之前调用,这当然意味着它是在引发preRenderView事件之后调用的.

Removed the e (damn you NetBeans!): <f:view contentType="text/html" beforePhase="#{userSessionBean.beforePhase}"> This is only called before the render response phase, which of course means it's called after the preRenderView event is raised.

推荐答案

为什么会发生这种情况,有什么方法可以解决?

<f:metadata>标签文档(第二段的重点是我的):

From the <f:metadata> tag documentation (emphasis of 2nd paragraph is mine):

声明此视图的元数据构面.这必须是<f:view>的子级. 此标记必须位于给定viewId的顶级XHTML文件中,或者位于模板客户端中,但不能位于模板中.实现必须确保构面的直接子级为UIPanel ,即使该方面只有一个孩子.实现必须将UIPanel的id设置为UIViewRoot.METADATA_FACET_NAME符号常量的值.

Declare the metadata facet for this view. This must be a child of the <f:view>. This tag must reside within the top level XHTML file for the given viewId, or in a template client, but not in a template. The implementation must insure that the direct child of the facet is a UIPanel, even if there is only one child of the facet. The implementation must set the id of the UIPanel to be the value of the UIViewRoot.METADATA_FACET_NAME symbolic constant.

因此,实际上必须在顶视图中,而不是模板中.

So, it really has to go in the top view, not in the template.

是否有更好的方法来确保在其他任何页面之前都对每个页面调用相同的方法?

在您的特定情况下,将登录的用户存储为会话范围内的受管bean的属性(而不是cookie),并使用

In your particular case, store the logged-in user as a property of a session scoped managed bean instead of a cookie and use a filter on the appropriate URL pattern to check it. Session scoped managed beans are in the filter available as HttpSession attributes. Homegrown cookies are unnecessary as you're basically reinventing the HttpSession here. Unless when you want a "remember me" facility, but this should not be solved this way. Do it in a filter as well.

这篇关于JSF 2 facelets&lt; f:metadata/&gt;在模板和页面中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆