java - 组件族、组件类型和渲染器类型之间的关系是什么?

标签 java jsf jakarta-ee custom-component renderer

我在学习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>

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

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

最佳答案

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

让我们引用 JSF 2.0 specification :

3.1.2 Component Type

While not a property of UIComponent, the component-type is an important piece of data related to each UIComponent subclass that allows the Application instance to create new instances of UIComponent subclasses with that type. Please see Section 7.1.11 “Object Factories” for more on component-type.

3.1.3 Component Family

Each standard user interface component class has a standard value for the component family, which is used to look up renderers associated with this component. Subclasses of a generic UIComponent class will generally inherit this property from its superclass, so that renderers who only expect the superclass will still be able to process specialized subclasses.

基本上,组件类型对于 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)给定的标签应该在 View 根(其类在 faces-config.xml 中定义)中创建给定组件类型的组件,并且它的渲染器类型应设置为给定的渲染器类型。请注意,组件类型不是用于选择渲染器,而是用于在 View 根目录中创建组件。另请注意,渲染器类型条目是可选的。否则将使用组件自己的预定义渲染器类型。这允许使用不同的渲染器类型重用现有的组件类型。

关于java - 组件族、组件类型和渲染器类型之间的关系是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8076625/

相关文章:

java - logback:登录到 System.out 和错误时的竞争条件

java - 如何在单击按钮后打开新的 fxml View - JavaFX

java - 模板类型,如果模板是返回值 (Java)

java - 如何在mysql中获取正确的日期和时间格式?

jsf - Primefaces 选项列表。 DualListModel 的 Setter 删除源和目标

security - JSF 2.0 如何防止 CSRF

java - 编写自定义 HtmlResponseWriter JSF

java - 在 google appengine 部署 war 文件后从内部检查 war 文件

java - 在单例bean的生命周期回调中取消计时器

java - JAVA 的 future 会因为新的 Oracle 许可更新吗?