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

时间:2011-07-25 20:33:29

标签: jsf-2 facelets custom-component composite-component tagfile

我最近开始在Facelets中使用JSF 2.0,并且对于了解现有<ui:include>的新复合组件以及Facelets 1.x提供的其他模板技术感到困惑。

这些方法有什么区别?从功能上看,他们似乎提供了相同的内容:<ui:param> vs <cc:attribute><ui:insert> + <ui:define> vs标记文件,重用现有模板。除了复合组件的语法和清晰的接口规范之外还有什么吗?性能会有所不同吗?

1 个答案:

答案 0 :(得分:164)

  

这些方法有什么区别?

Facelet模板

如果要将主页面布局片段拆分为可重复使用的模板,请使用Facelet模板(如<ui:composition><ui:include><ui:decorate>)。例如。标题,菜单,内容,页脚等。

示例:

Facelet标记文件

如果您希望拥有可重复使用的组件组以防止/最小化代码重复,请使用Facelet标记文件。例如。一组标签+输入+消息组件。与复合组件的主要区别在于Facelet标记文件的输出不代表单个UIComponent,并且在某些情况下可能是复合组件不足时的唯一解决方案。通常,让<ui:include>具有一个或多个传递托管bean属性的<ui:param>(因此不是硬编码值)是包含文件最好是标记文件的信号。

示例:

复合组件

如果要使用纯XML创建单个且可重复使用的自定义UIComponent,则使用复合组件。这样的复合组件通常由一堆现有组件和/或HTML组成,并且物理地呈现为单个组件,并且应该绑定到单个bean属性。例如。由3个依赖java.util.Date组件表示单个<h:selectOneMenu>属性的组件,或将<p:fileUpload><p:imageCropper>组合到单个<my:uploadAndCropImage>中的组件,引用单个自定义com.example.Image实体作为财产。

示例:

自定义组件

只要使用Facelet标记文件或复合组件无法实现功能,就可以使用自定义组件,因为标准/可用组件集中缺乏支持。可以在开源组件库的源代码中找到示例,例如PrimeFacesOmniFaces

标记处理程序

如果要控制JSF组件树的构建而不是HTML输出的呈现,则应使用标记处理程序而不是组件。

示例:

示例项目

以下是一些利用上述所有技术的示例项目。


  

性能会有所不同吗?

从技术上讲,性能问题可以忽略不计。应根据具体功能要求以及实施的最终抽象程度,可重用性和可维护性来做出选择。每种方法都有其明确的目的和限制。

然而,在构建/恢复视图期间,复合组件会产生很大的开销(具体来说:在保存/恢复视图状态期间)。而且,在旧版本的Mojarra中,复合组件在分配默认值时存在性能问题,这已经从2.1.13开始修复。此外,当<cc:attribute method-signature>用于方法表达式时,Mojarra有memory leak,基本上整个组件树在HTTP会话中被重新引用,这是自2.1.29 / 2.2.8以来修复的。旧版2.1版本可以绕过内存泄漏,如下所示:

<context-param>
    <param-name>com.sun.faces.serializeServerState</param-name>
    <param-value>true</param-value>
</context-param>

或者在旧的2.2版本中如下:

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

但是,如果你有相对“很多”的复合组件,并且javax.faces.STATE_SAVING_METHOD设置为client,那么性能将会非常糟糕。如果您只想要使用简单的包含文件或标记文件已经可以实现的基本功能,请不要滥用复合组件。不要使用易于配置(阅读:不需要*.taglib.xml文件)作为优先考虑复合组件而不是标记文件的借口。

使用Mojarra 2.2.10或更早版本时,不要忘记禁用生产模式的相对较短的Facelets刷新周期:

<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>-1</param-value>
</context-param>

不要将此设置用于开发,否则您必须重新启动整个服务器才能反映Facelets文件中的更改!当-1未设置为javax.faces.PROJECT_STAGE时,Mojarra 2.2.11及更新版本和MyFaces默认为Development