Facelets — открытый веб-фреймворк, распространяемый под лицензией Apache license и альтернативная технология управления представлением для JavaServer Faces (JSF). Фреймворк требует для функционирования валидные XML документы. Это означает, что веб-страницы должны быть созданы с использованием языка разметки XHTML. Facelets поддерживает все компоненты JSF и создаёт собственное дерево компонент, отражая view (см. MVC) для JSF-приложения. В Facelets полностью устранена широко известная проблема смешанного контента, присущая JavaServer Faces.


Такое определение Facelets дает нам Википедия. И так было до JSF 2.

Документация от Sun (Oracle) для JSF 2 гласит, что термин Facelets используется для обозначения JavaServer Faces View Definition Framework (фреймворка для определения представления в JSF), который был разработан специально для использования совместно с технологией JavaServer Faces. Сейчас Facelets является частью спецификации JavaServer Faces, а также предпочтительной технологией для построения представлений в JSF-приложениях.

Технология JavaServer Pages, которая раньше использовалась в качестве технологии создания представлений в JSF-приложениях, не поддерживает новые функции, предоставляемые JSF 2, поэтому в официальной документации рекомендуется отказаться от нее в пользу XHTML.

Преимущества Facelets

Повторное использование кода и простота разработки имеют большое значение для разработчиков, выбравших технологию JSF 2 для разработки крупномасштабных проектов. Технология Facelets удовлетворяет потребности этих разработчиков за счет следующих преимуществ:

  • поддержки повторного использования кода посредством создания шаблонов и составных компонентов;
  • возможности функциональных расширений компонентов и других объектов на стороне сервера;
  • быстрого времени компиляции;
  • валидации EL-выражений во время компиляции;
  • высокой скорости работы технологии рендеринга страниц.

Что такое Facelets?

Facelets – это мощный, но в то же время легкий язык описания страниц, который используется для создания представлений в JavaServer Faces. Основополагающим понятием в технологии Facelets является дерево компонентов.

Facelets предоставляет разработчикам следующие возможности:

  • Использование XHTML для создания веб-страниц.
  • Поддержку библиотеки тэгов Facelets в дополнение к библиотекам тэгов JavaServer Faces и JSTL.
  • Поддержку единого унифицированного языка выражений (unified expression language).
  • Создание шаблонов для компонентов и страниц.

Web-страницы

Как уже говорилось выше и в предыдущих двух статьях, для создания фэйслетных представлений, используется технология XHTML. Реализация JSF 2 поддерживает XHTML-страницы, созданные в соответствии с XHTML Transitional DTD. В соответствии с соглашением, web-страницы, созданные с помощью технологии XHTML должны иметь расширение .xhtml.

Поддержка библиотек тэгов (Tag Library)

Технология JavaServer Faces поддерживает различные библиотеки тэгов для добавления компонентов на web-страницы. Чтобы включить поддержку библиотек в страницу, необходимо объявить их в тэге html с помощью пространств имен XML, например, так:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">

В следующей таблице приведены библиотеки тэгов, которые поддерживаются технологией Facelets.

Библиотека тэгов URI Префикс Пример Описание
JavaServer Faces Facelets Tag Library http://java.sun.com/jsf/facelets ui: ui:component
ui:insert
Тэги для работы с шаблонами
JavaServer Faces HTML Tag Library http://java.sun.com/jsf/html h: h:head
h:body
h:outputText
h:inputText
Тэги компонентов JavaServer Faces для всех UIComponents
JavaServer Faces Core Tag Library http://java.sun.com/jsp/jstl/core f: f:actionListener
f:attribute
Тэги для работы с событиями (actions) JavaServer Faces
JSTL Core Tag Library http://java.sun.com/jsp/jstl/core c: c:forEach
c:catch
JSTL 1.1 Core Tags
JSTL Functions Tag Library http://java.sun.com/jsp/jstl/functions fn: fn:toUpperCase
fn:toLowerCase
JSTL 1.1 Functions Tags

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

Что такое UIComponents я рассказывать здесь не буду, т.к. готовлю по этой теме отдельный пост.

Кроме приведенных в таблице библиотек тэгов, Facelets поддерживает тэги для составных компонентов, для которых вы можете определить свои префиксы.

Поддержка унифицированного языка выражений (Unified Expression Language)

Язык выражений (EL) в Facelets используется в основном для связывания объектов компонентов с методами или свойствами управляемых бинов (managed-bean). Например:

<h:inputText id="login_email" value="#{loginBean.email}" required="true"
                             label="#{msgs['login.input.email']}"
                             requiredMessage="#{msgs['login.input.email.required']}"/>

Здесь в атрибуте value указывается что компонент связан с полем email класса LoginBean, а значит, при отправке формы будет выполняться метод setEmail этого класса, а при рендеринге страницы – getEmail.

Шаблоны

В статье “Основы JSF 2.0” я уже приводил пример простого приложения на JSF 2. В нем я использовал технологию Facelets. В этой статье мы расширим наше приложение за счет использования технологии шаблонов, которую нам предоставляет Facelets.

JavaServer Faces 2.0 предоставляет инструменты для реализации пользовательских интерфейсов, которые легко расширяются и могут использоваться повторно. Шаблоны – одна из полезнейших возможностей технологии Facelets, которая позволяет создать страницу-шаблон, выступающую в роли контейнера для других страниц приложения. Технология шаблонизации в JSF позволяет многократно использовать однажды написанный код, что значительно увеличивает скорость разработки и спасает от глупых ошибок. Шаблоны также помогают стандартизировать внешний вид приложения с большим количеством страниц.

В следующей таблице приведены тэги Facelets, которые используются для создания шаблонов.

Тэг Описание
ui:component Определяет компонент, который будет создан и добавлен в дерево компонентов.
ui:composition Определяет состав страницы, которая использует шаблон. Содержимое за пределами этого тэга игнорируется. (См. пример ниже, там понятней).
ui:debug Определяет отладочный компонент, который будет создан и добавлен в дерево компонентов.
ui:define Определяет содержимое блока, который вставляется в страницу-шаблон.
ui:decorate Делает тоже самое что и тэг composition, но не игнорирует содержимое за пределами этого тэга.
ui:fragment Делает тоже самое что и тэг component, но не игнорирует содержимое за пределами этого тэга.
ui:include Инкапсулирует и использует повторно на нескольких страницах содержимое, которое описано в тэге.
ui:insert Вставляет содержимое в шаблон.
ui:param Используется для передачи параметров в включенный (include) файл.
ui:repeat Используется в качестве альтернативы тэгам c:forEach или h:dataTable.
ui:remove Удаляет содержимое со страницы.

Итак, сейчас мы имеем (из статьи “Основы JSF 2.0″) JSF приложение с двумя страницами, ресурсным бандлом и простым бином.

Простой JSF-проект без шаблонов

Простой JSF-проект без шаблонов

Давайте добавим к этому приложению шаблон.

Для этого создайте в webapp (корень web-приложения) директорию tpl, в которой мы будем хранить шаблоны. В tpl создайте страницу regular.xhtml (regular – обычный). Создайте в каталоге resources директорию META-INF, а в ней директорию resources. Здесь или в корне web-приложения, согласно спецификации, нужно хранить все ресурсы web-приложения, будь то картинки, таблицы стилей, js-скрипты и т.д. В статье “Достоинства и недостатки JSF 2” в разделе “Обработка CSS и JavaScript” я писал что ресурсы можно группировать в библиотеки. Создайте в директории META-INF/resources/ директорию styles (или css, кому как удобней). Это и есть библиотека. В нее мы будем складывать все таблицы стилей.

Для наглядности я сгенерировал html-шаблон с помощью сервиса http://csstemplater.com. В библиотеку styles я положил две таблицы стилей (style.css и style_ie.css) из скачанного шаблона.

style.css:

* {
    margin: 0;
    padding: 0;
}
 
html {
    height: 100%
}
 
body {
    font: 12px / 18px Arial, Tahoma, Verdana, sans-serif;
    height: 100%;
}
 
a {
    color: blue;
    outline: none;
    text-decoration: underline;
}
 
a:hover {
    text-decoration: none;
}
 
p {
    margin: 0 0 18px
}
 
img {
    border: none;
}
 
input {
    vertical-align: middle
}
 
#wrapper {
    width: 100%;
    min-width: 900px;
    min-height: 100%;
    height: auto !important;
    height: 100%;
}
 
/* Header
-----------------------------------------------------------------------------*/
#header {
    height: 150px;
    background: #FFE680;
}
 
/* Middle
-----------------------------------------------------------------------------*/
#middle {
    width: 100%;
    padding: 0 0 100px;
    height: 1%;
}
 
#middle:after {
    content: '.';
    display: block;
    clear: both;
    visibility: hidden;
    height: 0;
}
 
#container {
    width: 100%;
    float: left;
    overflow: hidden;
}
 
#content {
    padding: 0 270px 0 0;
}
 
/* Sidebar Right
-----------------------------------------------------------------------------*/
.sr {
    float: left;
    margin-right: -3px;
    width: 250px;
    margin-left: -250px;
    position: relative;
    background: #FFACAA;
}
 
/* Footer
-----------------------------------------------------------------------------*/
#footer {
    margin: -100px auto 0;
    min-width: 900px;
    height: 100px;
    background: #BFF08E;
}

style_ie.css

* html #wrapper,
* html #footer {
    width: expression((documentElement.clientWidth||document.body.clientWidth)<900?'900px':'');
}

Теперь создадим шаблон. Откройте tpl/regular.xhtml и измените его следующим образом.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
 
<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <h:outputStylesheet library="styles" name="style.css"/>
    <!--[if lte IE 6]><h:outputStylesheet library="styles" name="style_ie.css"/><![endif]-->
 
    <title>Facelets Template</title>
</h:head>
 
<h:body>
    <div id="wrapper">
 
        <div id="header">
            <ui:insert name="header">Header Section</ui:insert>
        </div>
        <!-- #header-->
 
        <div id="middle">
 
            <div id="container">
                <div id="content">
                    <ui:insert name="content">Main Content</ui:insert>
                </div>
                <!-- #content-->
            </div>
            <!-- #container-->
 
            <div class="sidebar sr">
                <ui:insert name="sidebar">Sidebar Section</ui:insert>
            </div>
            <!-- .sidebar.sr -->
 
        </div>
        <!-- #middle-->
 
    </div>
    <!-- #wrapper -->
 
    <div id="footer">
         <ui:insert name="footer">Header Section</ui:insert>
    </div>
    <!-- #footer -->
</h:body>
</html>

Здесь вы видите HTML-страницу условно разбитую на четыре части: шапка, содержимое, сайдбар и подвал. В каждой части есть тэг ui:insert с атрибутом name. Это означает что сюда, можно вставить какие-нибудь данные.

Такая структура будет у всех страниц приложения. Теперь нам нужно встроить “клиентские” блоки в шаблон. Для этого используется тэг ui:composition. В следующем примере мы изменим страницы greeting.xhtml и response.xhtml так, чтобы они встраивались в только что созданный нами шаблон.

greeting.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
 
<h:body>
    <ui:composition template="tpl/regular.xhtml">
        <ui:define name="header">
            Это шапка из greeting.xhtml
        </ui:define>
 
        <ui:define name="content">
            <h:outputText value="#{msgs['hello.world']}"/>
 
            <h:form id="form">
                <h:commandLink action="#{sampleBean.storeMessage}">Go to hello world</h:commandLink>
            </h:form>
        </ui:define>
 
        <ui:define name="sidebar">
            Сайдбар из greeting.xhtml
        </ui:define>
 
        <ui:define name="footer">
            Facelets &copy;
        </ui:define>
 
    </ui:composition>
</h:body>
</html>

response.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
 
<h:body>
 
    <ui:composition template="tpl/regular.xhtml">
        <ui:define name="header">
            Это шапка из response.xhtml
        </ui:define>
 
        <ui:define name="content">
            Message: #{sampleBean.message}
        </ui:define>
 
        <ui:define name="sidebar">
            Сайдбар из response.xhtml
        </ui:define>
 
        <ui:define name="footer">
            Facelets Response Page &copy;
        </ui:define>
 
    </ui:composition>
</h:body>
</html>

Теперь можно запустить приложение и убедиться, что блоки вставляются в шаблон. Facelets позволяет встраивать шаблон в шаблон и т.д. Например, у вас есть общий шаблон страницы и есть шаблон для сайдбара. Вы можете вставлять в сайдбар какие-нибудь блоки, а затем вставить сайдбар в общий шаблон.

Напоследок попытаюсь немного рассказать о композитных компонентах. Сам в них еще не очень хорошо разобрался.

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

JavaServer Faces вместе с технологией Facelets предлагают нам концепцию составных компонентов. Составные компоненты можно считать особым типом шаблона, который выступает в роли компонента.

Любой компонент по сути является частью повторно используемого кода, выполняющего определенные функции. Например, компонент inputText может принимать ввод пользователя. Любой компонент может иметь валидаторы, конверторы, слушатели, которые присоединяются к нему для выполнения некоторых определенных действий. Композитный компонент – это компонент, который состоит из разметки и других существующих компонентов. Это многоразовый компонент, созданный пользователем, настраиваемый, выполняющий определенные функции, имеющий возможность подключать валидаторы, конверторы и слушатели как и любой другой компонент JavaServer Faces.

Благодаря Facelets, любая XHTML-страница, состоящая из разметки и других компонентов, может быть преобразована в составной компонент. Благодаря технологии ресурсов (с помощью которой мы храним, например, таблицы стилей), составные компоненты можно хранить в библиотеках.

Замечание: на многих форумах спрашивают, нужно ли включать библиотеку jsf-facelets.jar в проект при использовании JSF 2. Ответ: нет. Включать эту библиотеку в проект не нужно, так как Facelets уже встроен в JSF 2.

Все. Примеры составных компонентов ищите в следующих статьях ;-)