组件系列,组件类型和渲染器类型之间的关系是什么?

car*_*wan 22 java jsf renderer java-ee custom-component

当我在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>
Run Code Online (Sandbox Code Playgroud)

我还在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>
Run Code Online (Sandbox Code Playgroud)

这种配置非常有效.但是,我不明白为什么<component-family>javax.faces.Panel</component-family>在渲染器注册时需要该行.在my.taglib.xml,组件和渲染器是连接的,恕我直言,它应该足以为组件选择合适的渲染器.附加参数的用途是什么<component-family>

我做了谷歌研究,我得到的所有答案都说"一个渲染器可以用来渲染多个组件.这些组件属于一个系列".但这些陈述并没有明确我的困惑.有人可以解释组件类型,组件系列和渲染器选择策略之间的关系吗?(希望有一个很好的例子.)

Bal*_*usC 37

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

让我们引用JSF 2.0规范:

3.1.2组件类型

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

3.1.3组件系列

每个标准用户界面组件类都具有组件系列的标准值,用于查找与此组件关联的渲染器.泛型UIComponent类的子类通常会从其超类继承此属性,因此只需要超类的渲染器仍然可以处理专门的子类.

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

UIComponent component = context.getApplication().createComponent("study.faces.Div");
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,组件study.faces.Div是不是编译时的依赖,从而提供运行时多态性和可插拔的可能性(如果您熟悉JDBC的Class#forName()机制和它的工厂,那么你就会明白,部分更好).

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

Renderer renderer = context.getRenderKit().getRenderer(component.getFamily(), component.getRendererType());
Run Code Online (Sandbox Code Playgroud)

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

以下faces-config.xml条目

<component>
    <component-type>study.faces.Div</component-type>
    <component-class>javax.faces.component.UIPanel</component-class>
</component>
Run Code Online (Sandbox Code Playgroud)

告诉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>
Run Code Online (Sandbox Code Playgroud)

告诉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>
Run Code Online (Sandbox Code Playgroud)

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