Ответ 1
В чем разница между этими подходами?
Шаблоны Facelet
Используйте шаблоны Facelet (как в <ui:composition>
, <ui:include>
и <ui:decorate>
), если вы хотите разделить фрагменты макета главной страницы на шаблоны многократного использования. Например, заголовок, меню, содержимое, нижний колонтитул и т.д.
Примеры:
- Как включить другой XHTML в XHTML, используя Facelet JSF 2.0?
- Какова реальная концептуальная разница между ui: decorate и ui: include?
- Как настроить h: head при использовании шаблона ui: Composition?
- Как изменить элементы заголовка страницы при использовании пользовательского интерфейса: состав
- Как ajax-обновить динамическое включение контента по меню навигации? (JSF SPA)
Файлы тегов Facelet
Используйте файлы тегов Facelet, если вы хотите иметь повторно используемую группу компонентов, чтобы предотвратить/минимизировать дублирование кода. Например, группа компонентов метка + вход + сообщение. Основное различие с составными компонентами состоит в том, что вывод файла тега Facelet не представляет отдельный UIComponent
и может в некоторых случаях быть единственным решением, когда составного компонента недостаточно. Как правило, наличие <ui:include>
с одним или несколькими <ui:param>
который передает свойство управляемого компонента (и, следовательно, не является жестко заданным значением), является сигналом того, что включаемый файл может быть файлом тегов.
Примеры:
- Как создать собственный тег Facelets?
- Как сделать сетку из композитного компонента JSF?
- Как создать составной компонент для столбца с данными?
- Primefaces outputLabel для составного компонента
Композитные компоненты
Используйте составные компоненты, если вы хотите создать один и многократно используемый пользовательский UIComponent
с единственной ответственностью, используя чистый XML. Такой составной компонент обычно состоит из набора существующих компонентов и/или HTML и физически отображается как отдельный компонент, и предполагается, что он связан с одним свойством компонента. Например, компонент, представляющий одно свойство java.util.Date
тремя зависимыми компонентами <h:selectOneMenu>
или компонент, который объединяет <p:fileUpload>
и <p:imageCropper>
в один элемент <my:uploadAndCropImage>
ссылающийся на один пользовательский com.example.Image
как свойство.
Примеры:
- Наша Вики-страница Композитный Компонент
- Код BalusC: составной компонент с несколькими полями ввода
- Разделить java.util.Date на два поля h: inputText, представляющие часы и минуты, с помощью f: convertDateTime
- Выберите все элементы в Multiple SelectManyCheckBox с динамическими идентификаторами
- Расширение компонента JSF commandLink
- Избегайте дублирования идентификаторов при повторном использовании композиций Facelets в том же контейнере именования
Пользовательские компоненты
Используйте пользовательский компонент всякий раз, когда функциональность не может быть достигнута с помощью файлов тегов Facelet или составных компонентов из-за отсутствия поддержки в стандартном/доступном наборе компонентов. Примеры можно найти повсюду в исходном коде библиотек компонентов с открытым исходным кодом, таких как PrimeFaces и OmniFaces.
Обработчики тегов
Если вы хотите управлять построением дерева компонентов JSF вместо рендеринга вывода HTML, вам следует использовать обработчик тега вместо компонента.
Примеры:
- Пользовательский компонент Facelet в JSF
- Как получить программный доступ к содержимому чего-либо, созданного с помощью <ui: define>?
- Условный рендеринг в tagfile в зависимости от того, указан атрибут или нет
- Выполнение перенаправления, когда преобразование/проверка, связанная с параметрами запроса, не удалась
Примеры проектов
Вот несколько примеров проектов, в которых используются все вышеперечисленные методы.
- Java EE Kickoff App (шаблоны - включает - tagfiles - составной)
- OmniFaces Showcase (шаблоны - включает в себя - tagfiles - составной)
Может ли производительность отличаться?
Технически проблема производительности незначительна. Выбор должен быть сделан на основе конкретных функциональных требований и конечной степени абстракции, возможности повторного использования и ремонтопригодности реализации. Каждый подход имеет свою четко определенную цель и ограничения.
Однако составные компоненты имеют значительные накладные расходы при создании/восстановлении представления (в частности, при сохранении/восстановлении состояния представления). И в более старых версиях Mojarra у составных компонентов были проблемы с производительностью при назначении значений по умолчанию, это уже исправлено с 2.1.13. Кроме того, у Мохарры была утечка памяти, когда для выражений методов используется <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
, тогда производительность будет javax.faces.STATE_SAVING_METHOD
. Не злоупотребляйте составными компонентами, если вы просто хотите получить базовую функциональность, которая уже возможна с простым включаемым файлом или файлом тега. Не используйте простоту настройки (читай: файл *.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
.