Когда использовать <ui: include>, файлы тегов, составные компоненты и / или пользовательские компоненты?

102

Недавно я начал использовать JSF 2.0 с Facelets и был озадачен новыми составными компонентами, зная существующие <ui:include>и другие методы создания шаблонов, предлагаемые Facelets 1.x.

В чем разница между этими подходами? Функционально они, кажется, предлагают примерно то же самое: файлы тегов <ui:param>vs <cc:attribute>, <ui:insert>+ <ui:define>vs, повторное использование существующих шаблонов. Есть ли что-нибудь помимо синтаксиса и четкой спецификации интерфейса в случае составных компонентов? Могут ли отличаться характеристики?

мрембиш
источник

Ответы:

176

В чем разница между этими подходами?

Шаблоны Facelet

Используйте шаблоны Facelet (например <ui:composition>, <ui:include>и <ui:decorate>), если вы хотите разделить фрагменты макета главной страницы на повторно используемые шаблоны. Например, заголовок, меню, контент, нижний колонтитул и т. Д.

Примеры:

Файлы тегов Facelet

Используйте файлы тегов Facelet, если вы хотите иметь повторно используемую группу компонентов, чтобы предотвратить / минимизировать дублирование кода. Например, группа компонентов label + input + message. Основное различие с составными компонентами состоит в том, что выходные данные файла тегов Facelet не представляют собой единичные данные UIComponentи могут в некоторых обстоятельствах быть единственным решением, когда составного компонента недостаточно. Как правило, наличие <ui:include>с одним или несколькими <ui:param>объектами, которые передают свойство управляемого компонента (и, следовательно, не жестко запрограммированное значение), является сигналом о том, что включаемый файл может лучше быть файлом тегов.

Примеры:

Композитные компоненты

Используйте составные компоненты, если вы хотите создать единый и многократно используемый заказ UIComponentс единой ответственностью, используя чистый XML. Такой составной компонент обычно состоит из группы существующих компонентов и / или HTML и физически отображается как один компонент и должен быть привязан к одному свойству bean-компонента. Например , компонент , который представляет собой единый java.util.Dateобъект по 3 зависимых <h:selectOneMenu>компонентов, или компонента , который сочетает в себе <p:fileUpload>и <p:imageCropper>в единую со <my:uploadAndCropImage>ссылкой единый пользовательский com.example.Imageобъект как собственность.

Примеры:

Пользовательские компоненты

Используйте пользовательский компонент, когда функциональность не может быть достигнута с помощью файлов тегов Facelet или составных компонентов из-за отсутствия поддержки в стандартном / доступном наборе компонентов. Примеры можно найти повсюду в исходном коде библиотек компонентов с открытым исходным кодом, таких как PrimeFaces и OmniFaces .

Обработчики тегов

Если вы хотите управлять построением дерева компонентов JSF вместо рендеринга вывода HTML, вам следует использовать обработчик тегов вместо компонента.

Примеры:

Примеры проектов

Вот несколько примеров проектов, в которых используются все вышеупомянутые методы.


Могут ли отличаться характеристики?

Технически проблема производительности незначительна. Выбор следует делать на основе конкретных функциональных требований и конечной степени абстракции, возможности повторного использования и ремонтопригодности реализации. У каждого подхода есть свои четко определенные цели и ограничения.

Однако составные компоненты имеют значительные накладные расходы во время построения / восстановления представления (в частности: во время сохранения / восстановления состояния представления). И в более старых версиях Mojarra у составных компонентов были проблемы с производительностью при назначении значений по умолчанию, это уже исправлено, начиная с 2.1.13. Кроме того, у Mojarra была утечка памяти, когда a <cc:attribute method-signature>использовалось для выражений методов, в основном все дерево компонентов повторно ссылается в сеансе HTTP, это исправлено, начиная с 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>

Не используйте этот параметр для разработки, иначе вам придется перезапустить весь сервер, чтобы изменения в файлах Facelets отразились! Mojarra 2.2.11 и новее, а MyFaces уже по умолчанию, -1когда javax.faces.PROJECT_STAGEне установлено Development.

BalusC
источник
почему вы хотите визуализировать 1 компонент (составной компонент) вместо, скажем, 3 (файл тегов лицевых панелей)? Я имею в виду, что в солнечный день вы, возможно, почувствуете себя 1, а не 3 ... но я думаю, что за этим стоит что-то еще. В вашем примере вы расширяете UINamingContainer ... может ли это быть одной из причин для перехода на cc (чтобы иметь возможность перезаписать некоторые функции, специфичные для реализации jsf)?
Toskan 06
2
Файл тегов следует рассматривать как своего рода включение. Составной компонент следует рассматривать как реальный компонент. Составной компонент требует реализации NamingContainer, в противном случае вы столкнетесь с проблемами дублирования идентификаторов, когда один и тот же компонент будет повторно использован несколько раз.
BalusC 06
@BalusC Допустим, у меня есть набор HTML и JSF, которые создают «блок», который позволяет мне добавлять или удалять адреса (и все его атрибуты: улица, номер, город и т. Д.). Мне нужно использовать тот же блок на 2 или 3 страницах. Подпадает ли это под ваше описание составного компонента?
RinaldoPJr
1
@Rinaldo: Думаю, я бы использовал для этого файл тегов с динамически заполняемыми идентификаторами компонентов, как показано в stackoverflow.com/questions/5713718/… . ИМО, если это можно сделать с файлом тегов, используйте его. Если это невозможно сделать с файлом тегов, используйте составной. Если вам нужно несколько компонентов для управления одним свойством (не адресом, а, например, названием улицы + номер дома, которые должны входить в одно свойство), то единственным решением будет составной компонент.
BalusC
2
@Tarik: у композитов много накладных расходов по сравнению с файлами тегов. Другими словами: плохая производительность. Используйте его только в том случае, если вам нужно создать один настраиваемый компонент пользовательского интерфейса на основе набора тесно связанных существующих компонентов. Это невозможно сделать с файлом тегов. ZEEF.com, например, имеет только один составной элемент: все-в-одном для загрузки / скачивания / кадрирования изображения, которое используется в изображении страницы, изображении профиля, заголовке блока ссылок, блоках изображений и т. Д. Он привязан только к Imageсвойству в фасоли.
BalusC