组件族、组件类型和渲染器类型之间的关系是啥?

Posted

技术标签:

【中文标题】组件族、组件类型和渲染器类型之间的关系是啥?【英文标题】:What is the relationship between component family, component type and renderer type?组件族、组件类型和渲染器类型之间的关系是什么? 【发布时间】:2011-12-25 23:19:55 【问题描述】:

我在学习JSF中的自定义组件开发时,对组件族、组件类型和渲染器类型之间的关系感到困惑。例如,我注册了一个渲染器和一个自定义组件,如下所示。

faces-config.xml:

<component>
    <component-type>study.faces.Div</component-type>
    <component-class>javax.faces.component.UIPanel</component-class>
</component>

<render-kit>
    <render-kit-id>html_BASIC</render-kit-id>
    <renderer>
        <component-family>javax.faces.Panel</component-family>
        <renderer-type>study.faces.DivRenderer</renderer-type>
        <renderer-class>com.study.ui.DivRenderer</renderer-class>
    </renderer>
</render-kit>

我还在my.taglib.xml 文件中注册了一个新标签,如下所示:

<tag>
    <tag-name>div</tag-name>
    <component>
        <component-type>study.faces.Div</component-type>
        <renderer-type>study.faces.DivRenderer</renderer-type>
    </component>
</tag>

此配置效果很好。但是,我不明白为什么在渲染器注册时需要&lt;component-family&gt;javax.faces.Panel&lt;/component-family&gt; 行。在my.taglib.xml 中,组件和渲染器是连接的,恕我直言,为组件选择合适的渲染器就足够了。附加参数&lt;component-family&gt;有什么用?

我做了谷歌研究,得到的所有答案都说“一个渲染器可用于渲染多个组件。这些组件属于一个家族”。但是这些陈述并没有消除我的困惑。有人能解释一下组件类型、组件族和渲染器选择策略之间的关系吗? (希望有一个很好的例子。)

【问题讨论】:

【参考方案1】:

渲染器是由组件系列选择的,而不是您所期望的组件类型。

让我们引用JSF 2.0 specification:

3.1.2 组件类型

虽然不是 UIComponent 的属性,但组件类型是与每个 UIComponent 子类相关的重要数据,它允许 Application 实例创建具有该类型的 UIComponent 子类的新实例。有关组件类型的更多信息,请参阅第 7.1.11 节“对象工厂”。

3.1.3 组件族

每个标准用户界面组件类都有一个组件族的标准值,用于查找与该组件关联的渲染器。通用 UIComponent 类的子类通常会从其超类继承此属性,因此只期望超类的渲染器仍然能够处理专门的子类。

基本上,组件类型对于JSF是必需的,以便通过Application#createComponent()方法创建组件。

UIComponent component = context.getApplication().createComponent("study.faces.Div");

这样做的好处是组件study.faces.Div 不是编译时依赖项,因此提供了运行时多态性和可插入性可能性(如果您熟悉JDBC's Class#forName() mechanism and its factories,那么您会更好地理解该部分)。

每个组件类型都属于一个可以由一个或多个组件组成的系列。渲染器由RenderKit#getRenderer()根据组件族和渲染器类型选择

Renderer renderer = context.getRenderKit().getRenderer(component.getFamily(), component.getRendererType());

根据组件类型和渲染器类型选择渲染器。这允许对属于组件系列的多个组件类型重用渲染器。否则,您需要为每个组件注册一个渲染器,即使这些组件可以共享同一个渲染器。

以下faces-config.xml条目

<component>
    <component-type>study.faces.Div</component-type>
    <component-class>javax.faces.component.UIPanel</component-class>
</component>

告诉 JSF Application 应该在创建给定组件类型的组件时创建给定组件类的实例。那里没有指定组件系列,因为 component.getFamily() 已经隐式知道了。

以及下面的faces-config.xml 条目

<render-kit>
    <renderer>
        <component-family>javax.faces.Panel</component-family>
        <renderer-type>study.faces.DivRenderer</renderer-type>
        <renderer-class>com.study.ui.DivRenderer</renderer-class>
    </renderer>
</render-kit>

告诉 JSF,每当请求给定组件系列和渲染器类型的渲染器时,RenderKit 应该返回给定渲染器类的实例。

以下.taglib.xml条目

<tag>
    <tag-name>div</tag-name>
    <component>
        <component-type>study.faces.Div</component-type>
        <renderer-type>study.faces.DivRenderer</renderer-type>
    </component>
</tag>

告诉 JSF(好吧,Facelets)给定标签应该在视图根中创建给定组件类型的组件(其类在 faces-config.xml 中定义),并且它的渲染器类型应该设置为给定渲染器类型。请注意,组件类型不是用于选择渲染器,而是用于在视图根目录中创建组件。另请注意,渲染器类型条目是可选的。否则将使用组件自己的预定义渲染器类型。这允许使用不同的渲染器类型重用现有的组件类型。

【讨论】:

非常感谢。答案非常详细和明确。它真的帮助我摆脱了困扰我一个多星期的困惑。我很遗憾 *** 不允许我给你多个赞成票。再次感谢您。【参考方案2】:

javadoc 表示getFamily()

返回该组件所在的组件族的标识符 属于。此标识符与 rendererType 属性,可用于select 适当的 Renderer 用于此组件实例。

the JSF specification 中涵盖了维护者的基本原理:

组件系列

每个标准用户界面组件类都有一个标准值 组件族,用于查找关联的渲染器 有了这个组件。通用UIComponent 类的子类 通常会从它的超类继承这个属性,所以 只期望超类的渲染器仍然能够处理 专门的子类。

我将此解释为提供了一些超越 Java 类类型的额外类型检查能力(因为子类将始终是子类。)我不确定这到底有多大用处。

【讨论】:

以上是关于组件族、组件类型和渲染器类型之间的关系是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在一个单元格渲染器中渲染 2 个组件

在等待在 ReactJS 渲染中获取数据时显示加载微调器

带有属性选择器的组件导致子元素不渲染

rest framework 之渲染器

由于上下文中未使用的属性,组件重新渲染

JSF 组件渲染器中的 JSF 标记