正确使用 Facelet 模板和复合组件

Posted

技术标签:

【中文标题】正确使用 Facelet 模板和复合组件【英文标题】:Proper using of Facelet templates & Composite Components 【发布时间】:2012-04-20 19:27:29 【问题描述】:

我仍然不确定如何正确使用 JSF 模板和复合组件。我需要创建一个企业 Web 应用程序,它会有很多页面。每个页面都有相同的页眉、菜单、页脚,当然还有不同的内容(= JSF 模板)。每个页面上的内容都由可重复使用的“盒子”(= JSF 复合组件)组成。这些框由一些文件、按钮等组成。我的解决方案是否正确?或者我应该使用其他技术,如自定义组件、装饰......?

layout.xhtml

<h:body>
    <ui:insert name="main_menu">
        <ui:include src="/xhtml/template/main_menu.xhtml"/>
    </ui:insert>
    <ui:insert name="header">
        <ui:include src="/xhtml/template/header.xhtml"/>
    </ui:insert>
    <ui:insert name="content"/>
    <ui:insert name="footer">
        <ui:include src="/xhtml/template/footer.xhtml"/>
    </ui:insert>
</h:body>

customer_overview.xhtml:

<html xmlns:cc="http://java.sun.com/jsf/composite/composite_component">
<h:body>
    <!-- Facelet template -->
    <ui:composition template="/xhtml/template/layout.xhtml">
        <ui:define name="content">
            <!-- Composite Components -->
            <cc:component_case_history
                caseList="#customerOverviewController.cases"
            />
            <cc:component_customer
                ....
            />
            ...
        </ui:define>
    </ui:composition>
</h:body>

component_case_history.xhtml

<html xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
    <composite:attribute name="cases" type="java.util.List"/>
</composite:interface>

<composite:implementation>
    <!-- using of "cases" -->
    ...
</composite:implementation>

CustomerOverviewController.java

@ManagedBean
@ViewScoped
public class CustomerOverviewController 
    public List<Case> getCases() 
        ...
    

编辑 2012-04-27

基于: When to use <ui:include>, tag files, composite components and/or custom components?

我认为我应该使用 Facelet 模板 + Facelet 标签文件,而不是 Facelet 模板 + 复合组件。

【问题讨论】:

你能把你的问题说得更具体一些吗?基本思想是一个模板将有多个客户端,允许重用。然后,所有客户共享相同的外观和感觉,并在彼此之间导航。在我(有限的)经验中,xhtml 相当简单,JSF 2.1 导航不是那么多。当然,您可以拥有代码 sn-ps、标头等,以便您的 HTML 遵循 DRY。你在问什么?顺便提一下,“@ManagedBean”与“@Named”有很大不同,仅供参考。 @Thufir:我在问我是否应该为我的 Web 应用程序 JSF 模板使用(根据您的评论,答案是肯定的),如果我应该用于必须可重复使用的“盒子” ,JSF 复合组件,或不同的东西(装饰,自定义组件).. 不确定。我不知道您所说的“HTML 遵循 DRY”是什么意思,也不知道您为什么提到“@ManagedBean”与“@Named”有很大不同。 DRY=="不要重复自己",参见***。哦,我提到“@Named”是因为我在打架——这与你的问题无关,抱歉。 【参考方案1】:

布局、模板

layout.xhtml:

每个页面都有相同的页眉、菜单、页脚...

在这种情况下,您可以省略页眉、菜单、页脚的 ui:insert 标记。

<h:body>
    <ui:include src="/xhtml/template/main_menu.xhtml"/>
    <ui:include src="/xhtml/template/header.xhtml"/>
    <ui:insert name="content"/>
    <ui:include src="/xhtml/template/footer.xhtml"/>
</h:body>

你也可能有一个没有名字的 ui:insert,所以如果你想进一步简化:

<h:body>
    <ui:include src="/xhtml/template/main_menu.xhtml"/>
    <ui:include src="/xhtml/template/header.xhtml"/>
    <ui:insert/>
    <ui:include src="/xhtml/template/footer.xhtml"/>
</h:body>

customer_overview.xhtml:

如果您在 layout.xhtml 中有没有名称的 ui:insert,则此处不需要 ui:define:

<ui:composition template="/xhtml/template/layout.xhtml">
        <!-- Composite Components -->
        <cc:component_customer/>
        <cc:component_case_history
            caseList="#customerOverviewController.cases"
        />
        ...
</ui:composition>

您还应该将模板放在用户无法直接访问的文件夹中 (WEB-INF)。

可重复使用的“盒子”

您的一个复合组件如下所示:

<cc:component_customer/>

没有任何属性的组件是非常可疑的。

它有什么作用? 显示用户名? 不传任何属性如何获取用户名?

组件应该是独立的,对于其他可重用的部分,请改用 ui:insert。

【讨论】:

我已经修复了 标签以避免误解。

以上是关于正确使用 Facelet 模板和复合组件的主要内容,如果未能解决你的问题,请参考以下文章

何时使用 <ui:include>、标记文件、复合组件和/或自定义组件?

嵌套 JSF 复合组件中的 AJAX

如何对 jsf 复合组件中的集合属性进行 bean 验证,约束不会触发

将 JavaScript 集成到 JSF 复合组件中,干净的方式

自定义复合控件在添加回 VGROUP 后仅 0.5-1 秒无法正确呈现

确定复合图案是不是正确使用