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

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

我最近开始将 JSF 2.0 与 Facelets 一起使用,但对已知现有的新复合组件感到困惑 <ui:include>以及 Facelets 1.x 提供的其他模板技术。

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

最佳答案

What is the difference between those approaches?


Facelet 模板
如果要将主页布局片段拆分为可重复使用的模板,请使用 Facelet 模板(如 <ui:composition><ui:include><ui:decorate> )。例如页眉、菜单、内容、页脚等。
例子:
  • How to include another XHTML in XHTML using JSF 2.0 Facelets?
  • What is the real conceptual difference between ui:decorate and ui:include?
  • How to customize h:head when using ui:composition template?
  • How to change head elements of a page when using ui:composition
  • How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)

  • Facelet 标记文件
    如果您希望拥有一组可重用的组件以防止/最小化代码重复,请使用 Facelet 标记文件。例如一组标签+输入+消息组件。与复合组件的主要区别在于 Facelet 标记文件的输出不代表单个 UIComponent在某些情况下,当复合组件不够用时,它可能是唯一的解决方案。一般来说,有一个 <ui:include>与一个或多个 <ui:param>传递托管 bean 属性(因此不是硬编码值)是一个信号,表明包含文件可以更好地作为标记文件。
    例子:
  • How to create a custom Facelets tag?
  • How to make a grid of JSF composite component?
  • How to create a composite component for a datatable column?
  • Primefaces outputLabel for composite component

  • 复合组件
    如果您想创建单个且可重复使用的自定义组件,请使用复合组件 UIComponent使用纯 XML 承担单一职责。这样的复合组件通常由一堆现有组件和/或 HTML 组成,并在物理上呈现为单个组件,并且应该绑定(bind)到单个 bean 属性。例如代表单个 java.time.LocalDate 的组件属性(property)由 3 个受抚养人 <h:selectOneMenu>表示日、月和年的组件,或组合 <p:fileUpload> 的组件和 <p:imageCropper>成单<my:uploadAndCropImage>指单定制com.example.Image实体作为属性(property)。
    例子:
  • Our Composite Component wiki page
  • The BalusC Code: Composite Component with multiple input fields
  • Split java.util.Date over two h:inputText fields representing hour and minute with f:convertDateTime
  • Select all items in Multiple SelectManyCheckBox with dynamic ids
  • Extending JSF commandLink component
  • Avoiding duplicate ids when reusing facelets compositions in the same naming container

  • 自定义组件
    当由于缺乏标准/可用组件集的支持而无法使用 Facelet 标记文件或复合组件实现功能时,请使用自定义组件。通常,当您想要对解码和/或编码进行高度控制和/或定制,并且还为最终用户提供相对容易地扩展/覆盖解码和/或编码的可能性时。示例在开源组件库的源代码中随处可见,例如PrimeFacesOmniFaces .
    标签处理程序
    当您想要控制 JSF 组件树的构建而不是 HTML 输出的呈现时,您应该使用标记处理程序而不是组件。
    例子:
  • Custom Facelet component in JSF
  • How can I access the content of something created with <ui:define> programmatically?
  • Conditional render in tagfile depending on whether the attribute is specified or not
  • Performing a redirect, when conversion / validation associated with query parameters fails

  • 示例项目
    以下是一些利用上述所有技术的示例项目。
  • Java EE Kickoff App ( templates - includes - tagfiles - composite )
  • OmniFaces Showcase ( templates - includes - tagfiles - composite )

  • Could performance differ?


    从技术上讲,性能问题可以忽略不计。应根据具体的功能需求和实现的最终抽象程度、可重用性和可维护性来进行选择。每种方法都有其明确的目的和局限性。
    然而,在构建/恢复 View 期间(特别是:在保存/恢复 View 状态期间),复合组件确实有很大的开销。而且,在旧版本的 Mojarra 中,复合组件在分配默认值时存在性能问题,自 2.1.13 以来已经修复。此外,Mojarra 有一个 memory leak<cc:attribute method-signature>用于方法表达式,基本上整个组件树都会在 HTTP session 中重新引用,这是自 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>
    
    不要将此设置用于开发,否则您必须重新启动整个服务器才能反射(reflect) Facelets 文件中的更改! Mojarra 2.2.11 和更新版本,MyFaces 已经默认为 -1javax.faces.PROJECT_STAGE未设置为 Development .

    关于jsf-2 - 何时使用 <ui :include>, 标记文件、复合组件和/或自定义组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6822000/

    相关文章:

    JSF 中的 Javascript - 没有库、没有名称和正文内容的 outputScript

    html - 我的 <ui :define name ="content"> tag doesn't appear in the JSF view 的内容

    java - 如 Windows 7 计算器中所示合并文本字段

    jsf-2 - 将 actionListener 方法名称作为参数传递以包含 View

    css - 将工具提示添加到子菜单

    jsf - 将 JSF 1.2 迁移到 2.x 导致 com.sun.faces.config.InitFacesContext.cleanupInitMaps 处出现 java.lang.NullPointerException

    javascript - 是否可以将计数添加到选择框?

    delphi - 在 Delphi 中使用 TOwnedCollection 后代

    spring - 如何使用 WebApplicationInitializer 配置素面 FileUploadFilter

    image - JSF 2.0 应用程序中的本地化图像