Подтвердить что ты не робот

Какова взаимосвязь между семейством компонентов, типом компонента и типом рендеринга?

Когда я изучаю разработку пользовательских компонентов в 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 компонент и средство визуализации подключены, и, IMHO, должно быть достаточно, чтобы выбрать соответствующий рендерер для компонента. В чем заключается использование дополнительного параметра <component-family>?

Я проводил исследования Google, и все ответы, которые я получил, говорят: "Один рендер может использоваться для рендеринга нескольких компонентов, которые принадлежат одному семейству". Но эти заявления не очистили мое замешательство. Может ли кто-нибудь объяснить взаимосвязь между типом компонента, семейством компонентов и стратегией выбора рендеринга? (Надеюсь, на хорошем примере.)

4b9b3361

Ответ 1

Средство рендеринга выбирается семейством компонентов, а не типом компонента, как вы ожидаете.

Пусть приведена спецификация JSF 2.0:

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 Class#forName() и его заводы, тогда вы поймете эту часть лучше).

Каждый тип компонента принадлежит к семейству, которое может состоять из одного или нескольких компонентов. Средство рендеринга выбирается на основе семейства компонентов и типа визуализатора с помощью 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 свойство, может использоваться для выбрать соответствующий Renderer для этого экземпляра компонента.

Обоснование сторонников приведено в спецификации JSF:

Семейство компонентов

Каждый класс компонентов стандартного пользовательского интерфейса имеет стандартное значение для семейство компонентов, которое используется для поиска связанных с визуализаторами с этим компонентом. Подклассы общего класса UIComponentкак правило, наследует это свойство от своего суперкласса, так что которые ожидают, что суперкласс все равно сможет обрабатывать специализированные подклассы.

Я интерпретирую это как предоставление некоторой возможности для дополнительной проверки типов за пределами типа класса Java (поскольку подклассы всегда будут подклассами.) Я не уверен, насколько это полезно на самом деле.