我在将我的JSF应用程序转换为可书籍标记的页面方面取得了很大进展,但我想知道我是否以正确的方式进行操作.一个问题是f:元数据标签是否有最佳实践位置?
我的典型Facelets客户端页面如下所示:
    <ui:composition template="./pattern.xhtml">
        <ui:define name="content">
            <f:metadata>
                <f:viewParam name="userId" value="#{bean.userId}" />
                <f:viewParam name="startRecord" value="#{bean.startRecord}" />
                <f:viewParam name="pageSize" value="#{bean.pageSize}" />
                <f:viewParam name="sort" value="#{bean.sort}" />
            </f:metadata>
            <h1>Data Table</h1>
etc
所以f:metadata和child f:viewParam标签在我的页面正文中遇到.我的pattern.xhtml模板还有一个部分(名为"header"),可以将这些标记放在标题部分.它们应该放在那里吗?它是否有所作为,或者我是否设置了一些我尚未见过的副作用?
我想在我的4个支持bean中的@PostConstruct中进行重定向.正如我从以下问题中学到的: JSF PostConstruct异常处理 - 重定向 我知道我应该使用:
    @PostConstruct
    public void init() {    
       if (shouldRedirect) {
          try { 
             FacesContext.getCurrentInstance().getExternalContext().redirect("bolagsSok_company.xhtml");
             return;
          } catch (IOException e) {
             //do nothing
          }
        }
        ....
     }
这适用于我的2个Backing bean ...但是对于其他两个,非重定向的xhtml文件仍然调用支持bean而不重定向.我已经确认(使用调试),支持bean确实调用了两个FacesContext.getCurrentInstance().getExternalContext().redirect("bolagsSok_company.xhtml");并返回; 声明.
有什么线索可能是错的?
我目前正在尝试将记录的ID从一个页面发送到另一个页面.
所以在第1页中,我有这样的事情:
<p:column>
    <h:link value="#{rpb.map['transNum']}" outcome="TInput.xhtml">
        <f:param name="id" value="#{rpb.map['id']}" />
    </h:link>
</p:column>
在目标页面(TInput.xhtml)中,我有类似的东西来捕获id:
....
    xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<f:metadata>
    <f:viewParam name="id" value="#{tInputBean.id}"></f:viewParam>
</f:metadata>
<h:head>
....
现在,单击链接,转到第2页,第2页由一个视图范围的jsf bean处理.从我的调试来看,这是发生的顺序:
我想要实现的是: 在更新模型之后,我想对该记录id执行查询,获取它的bean以及它来自Business Service的详细信息列表.
我想知道我应该在哪里放置我的查询代码:
请赐教:)
根据Glassfish3.1.1的Mojarra-2.1.3(随Netbeans7.1一起发布)
我有一个带有侦听器void reset()的@SessionScoped支持bean跟踪器.
以下在f:使用template.xhtml的所有XHTML页面的元数据中都可以正常工作,例如/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:事件是很繁琐的,我首先尝试将其放在我的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在区分使用不同id查询参数调用的不同block/view.xhtml?id = [id]页面时没有任何作用,viewId总是只是'/ block /view.xhtml".
在写这个stackoverflow发布期间,我发现了我的问题的解决方案:只需将f:event放在f:metadata.xhtml的元数据之外(我在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:元数据,在f:元素模板中使用f:事件.
BalusC在何时使用f:viewAction/preRenderView与PostConstruct?:
在每个HTTP请求上调用preRenderView事件.
如果我在最终XHTML页面的f:元数据中有preRenderView f:事件,或者在模板的f:元数据之外,但不在f:元数据中,那么这似乎只是真实的(按预期工作)模板.
关于是否应该在f:模板的元数据中使用f:event,或者在模板中使用f:metadata,似乎存在一些争论.
JSF2完全参考(Burns和Schalk)p.540指出:
f:metadata标记封装了用于指定Facelets视图的元数据的元素集,因此必须是f:view标记的子元素,并且可能不会出现在模板中.从JSF2.0开始,此标记的唯一目的是封装f:viewParam标记.
但是有很多关于f的Stackoverflow的例子:在模板中使用的元数据,并且有很多f:在f:metadata中使用的事件的例子.这也在这里讨论:
BalusC在哪里帮助解释:
.. <f:event>并非严格要求放在<f:metadata>中.它可以附加到任何组件...当你有一堆<f:viewParam>并且希望挂钩<f:event>以在所有那些视图参数之后调用一个动作时,确实存在于<f:metadata>内的纯自我纪录目的已经设定好了...
但我上面的经验表明,在f:模板的元数据中放置和f:事件会产生稍微不同(奇怪)的行为.为什么?
PF 3.5.10,Mojarra 2.1.21,Omnifaces 1.5
如何在加载.xhtml JSF页面之前调用特殊的init() - 某些(CDI)SessionScoped bean的方法?现在我调用init(),如果用户从站点菜单中选择页面(带p:menutitem).但是如果用户使用浏览器地址行直接输入url该怎么办?
编辑my.xhtml::
<ui:define template="/mytemp.xhtml">
   <f:event type="preRenderView" listener="#{mybean.init()}" />
   <h:form>
     <p:commandButton update="@form" ... />
   </h:form>
</ui:define>
如果我这样做,init()将在每次更新时调用(即每次回发到服务器),例如每次单击commandButton时.所以我不能使用你的提议.
编辑2:谢谢Luiggi Mendoza和BalusC!除了Luiggi Mendoza的解决方案之外,正如评论所述,Omnifaces 1.6也将拥有ViewScope.
jsf ×5
jsf-2 ×4
cdi ×1
composition ×1
events ×1
facelets ×1
metadata ×1
prerender ×1
templating ×1