blob: 3b283c5f5a4ffebd607b034d785d022115b15bb8 [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= Введение в JavaServer Faces 2.x
:jbake-type: tutorial
:jbake-tags: tutorials
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Введение в JavaServer Faces 2.x - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Введение в JavaServer Faces 2.x
JavaServer Faces (JSF) - это платформа разработки интерфейса пользователя для веб-приложений Java. Она призвана значительно упростить процесс создания и поддержки приложений, работающих на сервере приложений Java и визуализирующих свои пользовательские интерфейсы на целевом клиенте. JSF обеспечивает простоту использования благодаря целому ряду факторов:
* упрощает формирование пользовательского интерфейса из набора повторно используемых компонентов пользовательского интерфейса;
* упрощает перенос данных приложения в пользовательский интерфейс и из него;
* помогает управлять состоянием пользовательского интерфейса при запросах к серверу;
* предоставляет простую модель установления связи между созданными клиентом событиями и кодом приложения на стороне сервера;
* упрощает сборку и повторное использование компонентов пользовательского интерфейса.
Подробное описание платформы JSF приведено в link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop.htm[+учебном курсе по Java EE 7, Глава 12. Разработка по технологии JavaServer Faces+].
В этом учебном курсе описывается применение поддержки JSF 2.x к веб-приложениям с помощью IDE NetBeans. Сначала необходимо добавить поддержку платформы JSF 2.x к базовому веб-приложению, а затем приступить к выполнения следующих задач:
* создать управляемый компонент JSF для обработки данных запроса,
* подключить управляемый компонент к веб-страницам приложения и
* преобразовать веб-страницы в файлы шаблонов Facelets.
IDE NetBeans обеспечивает долгосрочную поддержку для JavaServer Faces. Начиная с редакции JSF 2.0 и Java EE 6, IDE NetBeans обеспечивает поддержку для JSF 2.0 и JSF 2.1. Подробнее см. в разделе link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+].
image::images/netbeans-stamp-80-74-73.png[title="Содержимое этой страницы применимо к IDE NetBeans 7.2, 7.3, 7.4 и 8.0"]
Для работы с этим учебным курсом требуются программное обеспечение и материалы, перечисленные ниже.
|===
|Программное обеспечение или материал |Требуемая версия
|link:https://netbeans.org/downloads/index.html[+IDE NetBeans+] |7.2, 7.3, 7.4, 8.0, пакет Java EE
|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Комплект для разработчика на языке Java (JDK)+] |7 или 8
|link:http://glassfish.dev.java.net/[+Сервер GlassFish+] |Open Source Edition 3.x или 4
|link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FjsfDemo.zip[+Проект веб-приложения `jsfDemo`+] |неприменимо
|===
*Примечания*
* В комплект Java в среде IDE NetBeans также входит сервер GlassFish - сервер, совместимый с Java EE, который требуется для этого учебного курса.
* Для сравнения проекта с рабочим решением загрузите link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FjsfDemoCompleted.zip[+выполненный демонстрационный проект+].
[[support]]
== Добавление поддержки JSF 2.x к веб-приложениям
Начните работу с открытия <<requiredSoftware,проекта веб-приложения `jsfDemo`>> в среде IDE. После открытия проекта в среде IDE в него можно добавить поддержку платформы с помощью окна "Свойства" в проекте.
IDE также позволяет создавать новые проекты с поддержкой JSF 2.x. Подробнее см. раздел link:jsf20-support.html#creatingSupport[+Создание нового проекта с поддержкой JSF 2.x+].
1. Нажмите кнопку 'Открыть проект' ( image:images/open-project-btn.png[] ) на главной панели инструментов IDE или нажмите Ctrl-Shift-O (⌘-Shift-O в Mac).
2. В диалоговом окне "Открытие проекта" перейдите к папке на компьютере, в которой хранится разархивированный файл учебного проекта. Выберите его, а затем для открытия проекта в среде IDE нажмите кнопку "Открыть проект".
*Примечание.* При открытии проекта NetBeans может быть отображен запрос на разрешение ссылки на библиотеки JUnit, если при установке IDE не был установлен подключаемый модуль JUnit.
. Выполните проект и посмотрите, как он выглядит в браузере. Либо щелкните правой кнопкой мыши узел проекта `jsfDemo` в окне 'Проекты' и выберите 'Запустить' или нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) на главной панели инструментов. Проект запакован и разворачивается на сервере GlassFish, а в браузере открывается страница приветствия(`index.xhtml`).
image::images/run-project.png[title="Запустите проект, чтобы просмотреть его в браузере."]
. Нажмите кнопку "Отправить". Страница ответа (`response.xhtml`) отображается следующим образом:
image::images/response.png[title="Страницы приветствия и отклика в настоящее время являются статическими страницами"]
В настоящее время страницы приветствия и отклика являются статическими, и совместно с файлом `stylesheet.css` и изображением `duke.png` они являются единственными файлами приложений, доступными из браузера.
. В окне 'Проекты' (Ctrl-1; -1 в Mac) щелкните правой кнопкой мыши узел проекта и выберите 'Свойства', чтобы открыть окно 'Свойства проекта'.
. Выберите категорию 'Платформы', а затем нажмите кнопку 'Добавить'.
. Выберите 'JavaServer Faces' в диалоговом окне 'Добавление платформы'. Нажмите кнопку 'ОК'.
image::images/add-framework.png[title="Добавление поддержки JSF к существующему проекту"]
После выбора "JavaServer Faces" станут доступными различные параметры настройки. На вкладке 'Библиотеки' вы можете указать, как проект обращается к библиотекам JSF 2.x. Доступная версия JSF будет зависеть от версии IDE и сервера GlassFish. По умолчанию используются библиотеки, поставляемые с сервером (сервером GlassFish). Тем не менее, в IDE также входят библиотеки JSF 2.x. (Можно выбрать параметр "Зарегистрированные библиотеки", если их необходимо использовать в проекте).
image::images/libraries-tab.png[title="Укажите доступ к библиотекам JSF 2.x"]
. Выберите вкладку "Настройка". Можно указать способ регистрации сервлета Faces в дескрипторе развертывания проекта. Также можно указать, нужно ли в проекте использовать страницы Facelets или JSP.
image::images/jsf-configuration.png[title="Укажите параметры сервлета Faces и предпочитаемый язык"]
Вы также можете легко настроить проект для использования различных наборов компонентов JSF на вкладке 'Компоненты'. Чтобы использовать набор компонентов, нужно загрузить необходимые библиотеки и использовать диспетчер Ant Library для создания новой библиотеки с библиотеками наборов компонентов.
image::images/jsf-components.png[title="Укажите параметры сервлета Faces и предпочитаемый язык"]
. Нажмите кнопку "ОК" для подтверждения изменений и закройте окно "Свойства проекта".
После добавления поддержки JSF к проекту дескриптор развертывания `web.xml` изменяется и выглядит следующим образом. (Изменения *выделены полужирным шрифтом*.)
[source,xml]
----
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
*<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>*
<welcome-file-list>
<welcome-file>*faces/*index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
----
*Важно!* Убедитесь, что файл `web.xml` содержит только одну запись `<welcome-file>` с компонентом '`faces/`', как показано в примере. Это обеспечивает передачу страницы приветствия проекта (`index.xhtml`) через сервлет Faces перед ее отображением в браузере. Это необходимо для верного отображения компонентов библиотек тегов Facelets.
Сервлет Faces регистрируется в проекте, и теперь страница приветствия `index.xhtml` при запросе передается через сервлет Faces. Кроме того, обратите внимание, что добавлена запись для параметра контекста `PROJECT_STAGE`. При установке значения этого параметра на "`Development`" предоставляется полезная информация во время отладки приложения. См. link:http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2[+http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2+] для получения дополнительной информации.
Для просмотра библиотек JSF разверните узел "Библиотеки" проекта в окне "Проекты". Если используются библиотеки по умолчанию, включенные в GlassFish Server 3.1.2 или GlassFish Server 4, под узлом сервера GlassFish отображается `javax.faces.jar`. (Если вы используете старую версию GlassFish, вы увидите библиотеки `jsf-api.jar` и `jsf-impl.jar`, а не `javax.faces.jar`.)
Поддержка JSF в среде IDE 2.x включает в себя в первую очередь большое количество мастеров для JSF, а также специальные функциональные возможности, предоставляемые редактором Facelets. Эти функциональные возможности описаны ниже. Подробнее см. в разделе link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+].
[[managedBean]]
== Создание управляемого компонента
Управляемые компоненты JSF для обработки данных пользователя и сохранения их между запросами. Управляемый компонент – это link:http://en.wikipedia.org/wiki/Plain_Old_Java_Object[+POJO+] (простой объект Java), который используется для сохранения данных и управляется контейнером (например, сервером GlassFish) с помощью платформы JSF.
Компонент POJO по существу является классом Java, который содержит публичный безаргументный конструктор и соответствует правилам присвоения имен link:http://download.oracle.com/javase/tutorial/javabeans/[+JavaBeans+] для свойств.
При просмотре <<staticPage,статической страницы>>, полученной в результате выполнения проекта, пользователю необходим механизм, который проверяет введенное пользователем число на соответствие текущему выбранному числу и возвращает представление, соответствующее полученному результату. Чтобы создать управляемый компонент для этих целей, используйте link:jsf20-support.html#managedBean[+Мастер создания управляемого компонента+] среды IDE. Страницы Facelets, создаваемые в следующем разделе, должны иметь доступ к числу, вводимому пользователем, и к сгенерированному ответу. Для упрощения добавьте свойства `userNumber` и `response` к управляемому компоненту.
* <<usingManagedBean,Использование мастера создания управляемого компонента>>
* <<creatingConstructor,Создание конструктора>>
* <<addingProperties,Добавление свойств>>
[[usingManagedBean]]
=== Использование мастера создания управляемого компонента
1. В окне 'Проекты' щелкните правой кнопкой мыши узел проекта `jsfDemo` и выберите 'Создать' > 'Управляемый компонент JSF'. (Если "Управляемый компонент" отсутствует, выберите "Другие". Затем выберите параметр "Управляемый компонент JSF" в категории "JavaServer Faces". Нажмите кнопку "Далее".
2. В мастере введите следующее:
* *Имя класса:* UserNumberBean;
* *Пакет:* guessNumber;
* *Имя:* UserNumberBean
* *Контекст:* сеанс
image::images/managed-bean.png[title="Используйте мастер управляемых компонентов JSF для создания нового управляемого компонента"]
. Нажмите кнопку "Завершить". Класс `UserNumberBean` будет создан и открыт в редакторе. Обратите внимание на следующие аннотации (*выделено полужирным шрифтом*):
[source,java]
----
package guessNumber;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
/**
*
* @author nbuser
*/
*@ManagedBean(name="UserNumberBean")
@SessionScoped*
public class UserNumberBean {
/** Creates a new instance of UserNumberBean */
public UserNumberBean() {
}
}
----
Поскольку вы используете JSF 2.x, можно объявить все относящиеся к JSF компоненты с помощью аннотаций. В предыдущих версиях их необходимо было объявлять в файле настройки Faces (`faces-config.xml`).
[tips]#Для просмотра документации Javadoc по всем аннотациям JSF 2.1 обратитесь к link:http://javaserverfaces.java.net/nonav/docs/2.1/managed-bean-javadocs/index.html[+Спецификации аннотации управляемого компонента Faces+].#
[[creatingConstructor]]
=== Создание конструктора
Конструктор `UserNumberBean` должен создавать случайное число от 0 до 10 и сохранять его в переменной экземпляра. Таким образом частично формируется бизнес-логика для приложения.
1. Определите конструктор для класса `UserNumberBean`. Введите следующий код (изменения выделены *полужирным шрифтом*).
[source,java]
----
public class UserNumberBean {
*Integer randomInt;*
/** Creates a new instance of UserNumberBean */
public UserNumberBean() {
*link:http://docs.oracle.com/javase/7/docs/api/java/util/Random.html[+Random+] randomGR = new Random();
randomInt = new Integer(randomGR.link:http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextInt%28int%29[+nextInt+](10));
System.out.println("Duke's number: " + randomInt);*
}
}
----
Вышеуказанный код создает случайное число от 0 до 10 и записывает это число в протокол сервера.
. Исправьте операторы импорта. Для этого щелкните метку4 подсказки ( image:images/hint-icon.png[] ), которая отображается на левой границе редактора, затем выберите параметр для импорта `java.util.Random` в класс.
. Повторно запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). При выполнении проекта файл протокола сервера автоматически открывается в окне вывода.
image::images/output1.png[title="Файл журнала сервера автоматически открывается в окне вывода."]
Обратите внимание на то, что в окне вывода не отображается "`Номер Дюка: `" (как указывалось в конструкторе). Объект `UserNumberBean` не создан, так как по умолчанию в JSF используется _"ленивое" создание экземпляра_. Таким образом, компоненты в определенных контекстах создаются и инициализируются, только если они необходимы в приложении.
Состояния link:http://javaserverfaces.java.net/nonav/docs/2.1/managed-bean-javadocs/index.html[+Документации Javadoc по аннотации `@ManagedBean`+]:
_Если атрибут `eager()` имеет значение `true`, а значением `managed-bean-scope` является "application", то в среде выполнения при запуске приложения должен быть создан экземпляр этого класса. Создание и сохранение экземпляра должно осуществляться до обслуживания запросов. Если атрибут _eager_ не указан либо имеет значение `false` или элементу `managed-bean-scope` не присвоено значение "приложение", по умолчанию происходит "ленивое" создание экземпляра и контекстное сохранение управляемого компонента._
. Поскольку класс `UserNumberBean` входит в контекст сеанса, реализуется интерфейс `Serializable`.
[source,java]
----
@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean *implements Serializable* {
----
Используйте метку подсказки ( image:images/hint-icon.png[] ) для импорта `java.io.Serializable` в класс.
[[addingProperties]]
=== Добавление свойств
Страницы Facelets, создаваемые в следующем разделе, должны иметь доступ к числу, вводимому пользователем, и к сгенерированному ответу. Для упрощения этого добавьте свойства `userNumber` и `response` к классу.
1. Начните с объявления `Integer` с именем `userNumber`.
[source,java]
----
@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean implements Serializable {
Integer randomInt;
*Integer userNumber;*
----
. Щелкните правой кнопкой мыши в редакторе и выберите команду "Вставить код" (ALT+INS; CTRL+I на компьютере Mac). Выберите методы получения и установки.
image::images/getter-setter.png[title="Используйте IDE для создания методов доступа для свойств"]
. Выберите параметр `userNumber`: `Integer`. Нажмите кнопку "Создать".
image::images/generate-getters-setters.png[title="Используйте IDE для создания методов доступа для свойств"]
Обратите внимание на то, что методы `getUserNumber()` и `setUserNumber(Integer userNumber)` добавлены в класс.
. Создайте свойство `response`. Объявите `String` с именем `response`.
[source,java]
----
@ManagedBean(name="UserNumberBean")
@SessionScoped
public class UserNumberBean implements Serializable {
Integer randomInt;
Integer userNumber;
*String response;*
----
. Создайте метод получения для `response`. (Для этого приложения не требуется метод установки). Для создания кода шаблона в среде IDE можно использовать всплывающее окно "Создание кода", упомянутое выше в действии 2. Однако в целях изучения данного руководства просто вставьте нижеуказанный метод в класс.
[source,html]
----
public String getResponse() {
if ((userNumber != null) &amp;&amp; (userNumber.link:http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#compareTo(java.lang.Integer)[+compareTo+](randomInt) == 0)) {
//invalidate user session
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
session.invalidate();
return "Yay! You got it!";
} else {
return "<p>Sorry, " + userNumber + " isn't it.</p>"
+ "<p>Guess again...</p>";
}
}
----
Вышеуказанный метод выполняет две функции.
1. Тестирует введенное пользователем число (`userNumber`) на равенство случайному числу, сгенерированному для сеанса (`randomInt`), и возвращает соответствующий ответ `String`.
2. Определяет пользовательский сеанс как недействительный, если пользователь ввел правильное число (т.е., если `userNumber` равно `randomInt`). Это необходимо для того, чтобы новое сгенерированное число побудило пользователя сыграть еще раз.
. Щелкните правой кнопкой мыши в области редактора и выберите команду "Исправить операторы импорта" (ALT+SHIFT+I; &amp;#8984+SHIFT+I на компьютере Mac). Параметры импорта автоматически создаются для:
* `javax.servlet.http.HttpSession`
* `javax.faces.context.FacesContext`
Можно нажать сочетание клавиш CTRL+ПРОБЕЛ на элементах в редакторе для вызова предложений автозавершения кода и поддержки документации. Нажмите сочетание клавиш CTRL+ПРОБЕЛ, установив курсор на `FacesContext`, для просмотра описания класса из документации Javadoc.
image::images/documentation-support.png[title="Для вызова поддержки автозавершения кода и документации нажмите сочетание клавиш CTRL+ПРОБЕЛ."]
Щелкните значок веб-браузера ( image:images/web-browser-icon.png[] ) в окне документации, чтобы открыть Javadoc во внешнем веб-браузере.
[[wire]]
== Установление связи между управляемым компонентом и страницами
Одной из первичных целей JSF является отмена необходимости записывать шаблонный код для управления объектами <<pojo,POJO>> и их взаимодействием с видами приложений. Пример этого был приведен в предыдущем разделе, в котором JSF создал объект `UserNumberBean` при выполнении приложения. Это представление называется link:http://martinfowler.com/articles/injection.html[+Инверсия управления+] (IoC). Оно позволяет контейнеру принимать на себя ответственность за управление частями приложения, иначе разработчику потребовалось бы написать код с повторениями.
В предыдущем разделе был создан управляемый компонент, генерирующий случайное число от 0 до 10. Также было создано два свойства `userNumber` и `response`, представляющие соответственно пользовательский ввод числа и ответ на вопрос пользователя.
В этом разделе показаны способы использования `UserNumberBean` и его свойств на веб-страницах. JSF позволяет это сделать с помощью языка выражения. Язык выражения используется для привязки значений свойств к компонентам пользовательского интерфейса JSF, содержащихся на веб-страницах приложений. В этом разделе также показано, как можно воспользоваться внутренними функциями навигации JSF 2.x для перемещения между индексом и страницами ответов.
Эта поддержка в среде IDE обеспечивается с помощью функции автозавершения кода и средств документации, которые вызываются нажатием сочетания клавиш CTRL+ПРОБЕЛ, когда курсор установлен на каком-либо элементе в редакторе.
Начните с внесения изменений в `index.xhtml`, затем измените `response.xhtml`. На обеих страницах замените элементы формы HTML их эквивалентами JSF, поскольку они определены в link:http://javaserverfaces.java.net/nonav/docs/2.1/vdldocs/facelets/index.html[+библиотеке тегов HTML для JSF+]. Затем используйте язык выражений JSF для привязки значений свойств к выбранным компонентам пользовательского интерфейса.
* <<index,index.xhtml>>
* <<response,response.xhtml>>
[[index]]
=== index.xhtml
1. Откройте страницу `index.xhtml` в редакторе. Дважды щелкните узел `index.xhtml` в окне "Проекты" или нажмите сочетание клавиш ALT+SHIFT+O для открытия диалогового окна "Переход к файлу".
Как индекс, так и страницы ответов уже содержат компоненты пользовательского интерфейса JSF, необходимые для этого упражнения. Просто раскомментируйте их и закомментируйте элементы HTML, используемые в настоящий момент.
. Закомментируйте элемент формы HTML. Для этого выделите элемент формы HTML, как показано на изображении ниже, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).
*Примечание. *Для выделения воспользуйтесь функцией перетаскивания в редакторе с помощью мыши или с помощью клавиатуры удерживайте клавишу Shift и используйте клавиши со стрелками.
image::images/comment-out.png[title="Выделите код, затем нажмите Ctrl-/ для закомментирования кода"]
Для переключения комментариев нажмите сочетание клавиш CTRL+/ (&amp;#8984+/ на компьютере Mac). Эту комбинацию клавиш также можно использовать для других типов файлов, например, Java и CSS.
. Раскомментируйте компонент формы HTML для JSF. Выделите этот компонент, как показано на рисунке ниже, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).
*Примечание.* Возможно, вам придется нажать Ctrl-/ дважды, чтобы раскомментировать код.
image::images/comment.png[title="Выделите закомментированный код, затем нажмите Ctrl-/ для удаления комментария"]
После того как компонент формы HTML для JSF раскомментирован, в редакторе будет указано, что теги `<h:form>`, `<h:inputText>` и `<h:commandButton>` не объявлены.
image::images/undeclared-component.png[title="Редактор обеспечивает сообщения об ошибках для необъявленных компонентов"]
. Для объявления этих компонентов используйте автозавершение кода IDE, чтобы добавить пространство имен библиотеки тегов в тег `<html>` страницы. Наведите курсор на любой из необъявленных тегов, нажмите Alt-Enter и нажмите Enter, чтобы добавить предложенные библиотеки тегов. (При наличии нескольких параметров перед нажатием клавиши ВВОД убедитесь, что выбран тег, отображаемый в редакторе.) Пространство имен библиотеки тегов HTML для JSF добавляется к тегу `<html>` (*выделено ниже полужирным шрифтом*), и указания на ошибки исчезают.
*Примечание.* Если в IDE нет возможности добавить библиотеку тегов, потребуется вручную изменить элемент ``<html>`` .
[source,java]
----
<html xmlns="http://www.w3.org/1999/xhtml"
*xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----
. Используйте язык выражения JSF для привязки свойства `userNumber` для `UserNumberBean` к компоненту `inputText`. Атрибут `value` используется для указания текущего значения визуализируемого компонента. Введите в код, отображаемый ниже *полужирным шрифтом*.
[source,java]
----
<h:form>
<h:inputText id="userNumber" size="2" maxlength="2" *value="#{UserNumberBean.userNumber}"* />
----
В языке выражения JSF используется синтаксис `#{}`. Внутри этих парных символов указывается имя требуемого управляемого компонента и его свойство, разделенные точкой (`.`). Теперь при отправке данных формы на сервер значение автоматически сохраняется в свойстве `userNumber` с помощью метода установки свойств (`setUserNumber()`). Кроме того, если страница запрошена и значение для `userNumber` уже установлено, значение автоматически отображается в визуализированном компоненте `inputText`. Дополнительные сведения приведены в link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop001.htm#BNAQP[+Руководстве по Java EE 7. Глава 12.1.2 Использование языка выражений для создания ссылок на управляемые сеансные объекты+].
. Укажите адресата для запроса, который вызывается при нажатии кнопки формы. В HTML-версии формы это возможно выполнить с помощью атрибута `action` тега `<form>`. С помощью JSF можно использовать атрибут `action` для `commandButton`. Кроме того, благодаря внутренней функции навигации JSF 2.x вам нужно только указать имя конечного файла без расширения.
Введите код, отображаемый ниже *полужирным шрифтом*.
[source,xml]
----
<h:form>
<h:inputText id="userNumber" size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
<h:commandButton id="submit" value="submit" *action="response"* />
</h:form>
----
В среде выполнения JSF осуществляется поиск файла с именем `response`. Предполагается, что расширение файла такое же, как у файла, из которого произошел запрос (`index*.xhtml*`), и поиск файла `response.xhtml` выполняется в папке исходного файла (т.е. в корневом веб-узле).
*Примечание. *JSF 2.x позволяет упростить разработку. При использовании JSF 1.2 для этого проекта необходимо объявить правило перехода в файле настройки Faces. Объявление правила может выглядеть следующим образом:
[source,xml]
----
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>response</from-outcome>
<to-view-id>/response.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
----
Нижеприведенные действия с 7 по 12 являются дополнительными. Если необходимо выполнить быструю сборку проекта, сразу перейдите к <<response,`response.xhtml`>>.
. Протестируйте, выполняется ли вызов метода `setUserNumber()` вышеуказанным выражением на языке выражения при обработке запроса. Для выполнения этого используйте отладчик Java среды IDE.
Переключите на класс `UserNumberBean` (нажмите сочетание клавиш CTRL+TAB и выберите из списка файл). Установите точку останова в сигнатуре метода `setUserNumber()`. Это можно сделать, щелкнув мышкой в области левого поля. Появится красный значок, указывающий, что точка останова метода установлена.
image::images/set-breakpoint.png[title="Щелкните левую границу редактора для задания точек останова"]
. Нажмите кнопку 'Отладка проекта' (image:images/breakpoint-btn.png[]) на главной панели инструментов IDE. Начинается сеанс отладки, и в браузере открывается страница приветствия проекта.
*Примечания.*
* Вам может быть предложено подтвердить порт сервера для отладки приложений.
* Если появится диалоговое окно 'Отладить проект', выберите опцию по умолчанию 'Java на стороне сервера' и нажмите кнопку 'Отладка'.
. В браузере введите номер в форму и нажмите кнопку "Отправить".
. Вернитесь в среду IDE и проверьте класс `UserNumberBean`. Отладчик приостановлен в методе `setUserNumber()`.
image::images/debugger-suspended.png[title="Выполняется приостановка отладчика в соответствии с точками останова"]
. Откройте окно "Переменные отладчика" (выберите "Окно" > "Отладка > "Переменные" или нажмите сочетание клавиш CTRL+SHIFT+1). На экран будут выведены значения переменных для точки, в которой приостановлен отладчик.
image::images/variables-window.png[title="Отслеживание значений переменных с помощью окна 'Переменные отладчика'"]
На приведенном выше изображении значение "`4`" предоставлено для переменной `userNumber` в сигнатуре `setUserNumber()`. (Число 4 введено в форму.) "`this`" относится к объекту `UserNumberBean`, созданному для пользовательского сеанса. Далее можно отметить, что значение свойства `userNumber` в настоящий момент равно `null`.
. На панели отладчика нажмите кнопку 'Вход в' ( image:images/step-into-btn.png[] ). Отладчик выполняет обработку строки, на которой он в настоящий момент приостановлен. Происходит обновление окна "Переменные" с указанием выполненных изменений.
image::images/variables-window2.png[title="Окно переменных обновляется при переходе по коду"]
Теперь свойству `userNumber` присвоено значение, введенное в форме.
. Выберите Отладка> Завершить сеанс отладки (Shift-F5; Shift-Fn-F5 на Mac) из главного меню, чтобы остановить отладчик.
[[response]]
=== response.xhtml
1. Откройте страницу `response.xhtml` в редакторе. В окне "Проекты" дважды щелкните узел `response.xhtml` или нажмите сочетание клавиш ALT+SHIFT+O для открытия диалогового окна "Переход к файлу".
2. Закомментируйте элемент формы HTML. Выделите открывающий и закрывающий теги HTML `<form>` и код между ними, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).
*Примечание: * Для выделения воспользуйтесь функцией перетаскивания в редакторе с помощью мыши или с помощью клавиатуры удерживайте клавишу Shift и используйте клавиши со стрелками.
. Раскомментируйте компонент формы HTML для JSF. Выделите открывающий и закрывающий теги `<h:form>` и код между ними, затем нажмите CTRL+/ (&amp;#8984+/ на компьютере Mac).
На данном этапе, код между тегами `<body>` выглядит следующим образом:
[source,html]
----
<body>
<div id="mainContainer">
<div id="left" class="subContainer greyBox">
<h4>[ response here ]</h4>
<!--<form action="index.xhtml">
<input type="submit" id="backButton" value="Back"/>
</form>-->
<h:form>
<h:commandButton id="backButton" value="Back" />
</h:form>
</div>
<div id="right" class="subContainer">
<img src="duke.png" alt="Duke waving" />
<!--<h:graphicImage url="/duke.png" alt="Duke waving" />-->
</div>
</div>
</body>
----
После того как компонент формы HTML для JSF раскомментирован, в редакторе будет указано, что теги `<h:form>` и `<h:commandButton>` не объявлены.
. Для объявления этих компонентов используйте автозавершение кода IDE, чтобы добавить пространство имен библиотеки тегов в тег `<html>` страницы.
Используйте поддержку автозавершения кода в редакторе для добавления необходимых пространств имен JSF к файлу. При выборе тега JSF или Facelets через автозавершение кода происходит автоматическое добавление требуемого пространства имен к корневому элементу документа. Подробнее см. в разделе link:jsf20-support.html#facelets[+Поддержка JSF 2.x в IDE NetBeans+].
Установите курсор на один из необъявленных тегов и нажмите сочетание клавиш CTRL+ПРОБЕЛ. Предложения автозавершения кода и отображения поддержки документации.
image::images/code-completion2.png[title="Для вызова рекомендаций по автозавершению кода и всплывающего окна документации"]
Нажмите ENTER. (При наличии нескольких параметров перед нажатием клавиши ВВОД убедитесь, что выбран тег, отображаемый в редакторе.) Пространство имен библиотеки тегов HTML для JSF добавляется к тегу `<html>` (*выделено ниже полужирным шрифтом*), и указания на ошибки исчезают.
[source,java]
----
<html xmlns="http://www.w3.org/1999/xhtml"
*xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----
. Укажите адресата для запроса, который вызывается при нажатии пользователем кнопки формы. Кнопку необходимо установить так, чтобы при ее нажатии пользователь возвращался на страницу-указатель. Для этого следует использовать атрибут `action` для `commandButton`. Введите в код, отображаемый *полужирным шрифтом*.
[source,xml]
----
<h:form>
<h:commandButton id="backButton" value="Back" *action="index"* />
</h:form>
----
*Примечание. * При вводе `action="index"` пользователи в работе зависят от функции явной навигации в JSF. При нажатии кнопки формы в среде выполнения JSF осуществляется поиск файла с именем `index`. Предполагается, что расширение файла такое же, как у файла, от которого был направлен запрос (`response*.xhtml*`), и поиск файла `index.xhtml` выполняется в папке исходного файла (т.е. в корневом веб-узле).
. Замените статический текст "[здесь ответ]" значением свойства `response` для `UserNumberBean`. Для этого используйте язык выражения JSF. Введите следующее (*выделено полужирным шрифтом*).
[source,html]
----
<div id="left" class="subContainer greyBox">
<h4>*<h:outputText value="#{UserNumberBean.response}"/>*</h4>
----
. Запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). При появлении в браузере страницы приветствия введите номер и нажмите `submit`. Страница ответа будет отображаться следующим образом (выводится на экран, если введен неправильный номер).
image::images/response2.png[title="Просмотрит текущее состояния проекта в браузере"]
Две ошибки в текущем состоянии страницы ответа:
1. Теги HTML `<p>` отображаются в ответном сообщении.
2. Кнопка "Назад" не отображается в правильном местоположении. (Сравните с <<originalVersion,исходной версией>>.)
При выполнении следующих двух шагов эти ошибки устраняются.
. Установите атрибут `escape` тега `<h:outputText>` на `false`. Установите курсор между `outputText` и `value`, вставьте пробел и нажмите сочетание клавиш CTRL+ПРОБЕЛ для вызова автозавершения кода. Прокрутите вниз для выбора атрибута `escape` и проверки документации.
image::images/escape-false.png[title="Нажмите Ctrl-Пробел для просмотра возможных значений атрибутов и документации"]
Как указано в документации, значение `escape` установлено по умолчанию на `true`. Это означает, что символы, которые стандартно анализируются как html, включены в строку, как указано выше. Установка значения на `false` означает, что символы, анализируемые как HTML, можно визуализировать как HTML.
Нажмите ENTER, затем в качестве значения введите `false`.
[source,xml]
----
<h4><h:outputText *escape="false"* value="#{UserNumberBean.response}"/></h4>
----
. Установите атрибут `prependId` тега `<h:form>` на `false`. Установите курсор сразу после "`m`" в `<h:form>` и вставьте пробел, затем нажмите сочетание клавиш CTRL+ПРОБЕЛ для вызова автозавершения кода. Прокрутите вниз для выбора атрибута `prependId` и проверки документации. Затем нажмите ENTER и в качестве значения введите `false`.
[source,java]
----
<h:form *prependId="false"*>
----
В JSF применяются внутренние идентификаторы для отслеживания компонентов пользовательского интерфейса. В текущем примере при проверке исходного кода визуализируемой страницы отображается следующее:
[source,xml]
----
<form id="j_idt5" name="j_idt5" method="post" action="/jsfDemo/faces/response.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt5" value="j_idt5" />
<input *id="j_idt5:backButton"* type="submit" name="j_idt5:backButton" value="Back" />
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="7464469350430442643:-8628336969383888926" autocomplete="off" />
</form>
----
Идентификатором элемента формы является `j_idt5`, и этот идентификатор _предшествует_ идентификатору кнопки "Назад", включенной в форму (*выделено полужирным шрифтом* в приведенном выше примере). Поскольку кнопка "Назад" зависит от правила стиля `#backButton` (определенного в `stylesheet.css`), это правило становится блокированным, если идентификатор JSF предшествует идентификатору кнопки. Этого можно избежать, если для `prependId` установить значение `false`.
. Повторно запустите проект (нажмите кнопку 'Запустить проект' ( image:images/run-project-btn.png[] ) или нажмите F6; fn-F6 в Mac). Введите число на странице приветствия, затем нажмите кнопку "Отправить". Теперь на странице ответа отображается ответное сообщение без тегов `<p>`, и кнопка "Назад" размещена правильно.
image::images/response3.png[title="Просмотрит текущее состояния проекта в браузере"]
. Нажмите кнопку "Назад". Поскольку текущее значение свойства `userNumber` для `UserNumberBean` привязано к компоненту `inputText` JSF, ранее введенное число теперь отображается в текстовом поле.
. Проверьте протокол сервера в окне вывода среды IDE (CTRL+4; &amp;#8984+4 на компьютере Mac) для определения правильного загаданного числа.
Если по каким-то причинам просмотреть протокол сервера невозможно, откройте его посредством переключения на окно "Службы" (CTRL+5; &amp;#8984+5 на компьютере Mac) и развертывания узла "Серверы". Затем щелкните правой кнопкой мыши сервер GlassFish, на котором развернут проект и выберите 'Просмотреть журнал сервера'. Если номер не отображается в журнале сервера, попробуйте повторно выполнить сборку приложения, щелкнув правой кнопкой мыши узел проекта и выбрав 'Очистка и сборка'.
. Введите правильное число и нажмите кнопку "Отправить". В приложении происходит сравнение введенного числа с текущим сохраненным числом и выводится соответствующее сообщение.
image::images/yay.png[title="При вводе соответствующего числа отображается правильный отклик"]
. Нажмите еще раз кнопку "Назад". Обратите внимание на то, что ранее введенное число более не отображается в текстовом поле. Следует помнить о том, что метод `getResponse()` для `UserNumberBean` <<getResponse,определяет текущий пользовательский сеанс как недействительный>> при угадывании правильного числа.
[[template]]
== Применение шаблона Facelets
Facelets сегодня является стандартной технологией отображения для JSF 2.x. Facelets - это облегченная платформа шаблонов, которая поддерживает все компоненты JSF пользовательского интерфейса и используется для построения и визуализации дерева компонентов JSF для просмотра приложений. Кроме того, эта технология обеспечивает поддержку разработки при возникновении ошибок языка выражений за счет возможности проверять трассировку стека, дерево компонентов и контекстные переменные.
Хотя, возможно, вы об этом не задумывались, файлы `index.xhtml` и `response.xhtml`, с которыми вы работаете в этом руководстве, являются страницами Facelets. Страницы Facelets имеют расширение `.xhtml` и, поскольку вы работаете в проекте JSF 2.x (библиотеки JSF 2.x включают в себя файлы JAR Facelets), эти представления способны надлежащим образом визуализировать дерево компонентов JSF.
Целью этого раздела является знакомство с созданием шаблона Facelets. Для проектов с несколькими представлениями зачастую полезно применять файл шаблона, определяющего структуру и внешний вид для нескольких представлений. При обслуживании запросов приложение вставляет динамически подготовленное содержимое во временный файл и отправляет результат обратно клиенту. Хотя данный проект имеет только два представления (страницу приветствия и страницу ответа), можно легко отметить, что большая часть содержимого в них дублируется. Это дублированное содержимое можно перенести в шаблон Facelets и создать файлы клиента шаблона для обработки содержимого, которое является специфичным для страницы приветствия и страницы ответа.
В среде IDE существует link:jsf20-support.html#faceletsTemplate[+мастер создания шаблона Facelets+] для создания шаблонов Facelets и мастер создания клиента шаблона Facelets для создания файлов, зависящих от шаблона. В этом разделе описано использование этих мастеров.
*Примечание.* IDE также предоставляет мастер страниц JSF, что позволяет создавать индивидуальные страницы Facelets для проекта. Подробнее см. в разделе link:jsf20-support.html#jsfPage[+Поддержка JSF 2.x в IDE NetBeans+].
* <<templateFile,Создание файла шаблона Facelets>>
* <<templateClient,Создание файлов клиента шаблона>>
[[templateFile]]
=== Создание файла шаблона Facelets
1. Создайте файл шаблона Facelets. Нажмите сочетание клавиш CTRL+N (&amp;#8984+N на компьютере Mac) для открытия мастера создания файлов. Выберите категорию "JavaServer Faces", затем "Шаблон Facelets". Нажмите кнопку "Далее".
2. В поле "Имя файла" введите `template`.
3. Выберите один из восьми стилей размещения и нажмите кнопку "Готово". (Вы будете использовать существующую таблицу стилей, так что не имеет значения, какой стиль вы выберете.)
image::images/layout-style.png[title="Мастер шаблонов Facelets позволяет сделать выбор из распространенных стилей компоновки"]
Мастером будут созданы файл `template.xhtml` и сопутствующие таблицы стилей на основе выбора, которые будут помещены в папку `resources` > `css` в корневом веб-узле проекта.
После завершения выполнения мастера в редакторе открывается файл шаблона. Для просмотра шаблона в браузере, щелкните правой кнопкой мыши в редакторе и выберите 'Просмотр'.
. Проверьте разметку файла шаблона. Обратите внимание на следующие моменты.
* Библиотека тегов `facelets` объявлена в теге `<html>` страницы. Библиотека тегов имеет префикс `ui`.
[source,java]
----
<html xmlns="http://www.w3.org/1999/xhtml"
*xmlns:ui="http://xmlns.jcp.org/jsf/facelets"*
xmlns:h="http://xmlns.jcp.org/jsf/html">
----
* На странице Facelets используются теги `<h:head>` и `<h:body>` вместо тегов HTML `<head>` и `<body>`. При использовании этих тегов у Facelets появляется возможность создания дерева компонентов, которое включает в себя всю страницу.
* Страница ссылается на таблицы стилей, которые также создаются при завершении выполнения мастера.
[source,xml]
----
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
*<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />*
*<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />*
<title>Facelets Template</title>
</h:head>
----
* Теги `<ui:insert>` используются в теле страницы для каждого раздела, связанного с выбранным стилем размещения. Каждый тег `<ui:insert>` имеет атрибут `name`, определяющий раздел. Например:
[source,html]
----
<div id="top">
*<ui:insert name="top">Top</ui:insert>*
</div>
----
. Повторно проверьте страницу <<staticPage,приветствия>> и страницу <<responsePage,ответа>>. Содержимым, которое изменяется на этих страницах, является только заголовок и текст в сером квадрате. Следовательно, шаблон может включать в себя все остальное содержимое.
. Замените все содержимое файла шаблона содержимым, приведенным ниже.
[source,html]
----
<?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://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="css/stylesheet.css" rel="stylesheet" type="text/css" />
<title><ui:insert name="title">Facelets Template</ui:insert></title>
</h:head>
<h:body>
<div id="left">
<ui:insert name="box">Box Content Here</ui:insert>
</div>
</h:body>
</html>
----
Приведенный выше код реализует следующие изменения.
* Файл `stylesheet.css` проекта заменяет ссылки на таблицу стилей шаблона, созданные в мастере.
* Все теги `<ui:insert>` (вместе с тегами `<div>`) удаляются за исключением одного с именем `box`.
* В теги `<ui:insert>` вставляется заголовок страницы с именем `title`.
. Скопируйте в шаблон соответствующий код из файла `index.xhtml` или файла `response.xhtml`. Добавьте содержимое, отображаемое ниже *полужирным шрифтом*, в теги `<h:body>` файла шаблона.
[source,html]
----
<h:body>
*<div id="mainContainer">*
<div id="left" *class="subContainer greyBox"*>
<ui:insert name="box">Box Content Here</ui:insert>
</div>
*<div id="right" class="subContainer">
<img src="duke.png" alt="Duke waving" />
</div>
</div>*
</h:body>
----
. Выполните проект. При открытии страницы приветствия в браузере измените URL-адрес на следующий:
[source,java]
----
http://localhost:8080/jsfDemo/faces/template.xhtml
----
Файл шаблона отображается следующим образом:
image::images/facelets-template.png[title="Просмотрите шаблон Facelets в браузере"]
Теперь проект включает в себя файл шаблона, предоставляющий внешний вид и структуру всех представлений. Теперь можно создавать файлы клиента для вызова шаблона.
[[templateClient]]
=== Создание файлов клиента шаблона
Создайте файлы клиента шаблона для страниц приветствия и ответа. Укажите имя файла клиента шаблона для страницы приветствия `greeting.xhtml`. Для страницы ответа файл `response.xhtml`.
==== greeting.xhtml
1. Нажмите сочетание клавиш CTRL+N (⌘-N на компьютере Mac) для открытия мастера создания файлов. Выберите категорию "JavaServer Faces", затем "Клиент шаблона Facelets". Нажмите кнопку "Далее".
2. В поле "Имя файла" введите `greeting`.
3. Нажмите кнопку "Обзор" рядом с полем "Шаблон", затем в открывшемся диалоговом окне перейдите к файлу `template.xhtml`, созданному в предыдущем разделе.
image::images/template-client.png[title="Мастер создания клиентов шаблона Facelets"]
. Нажмите кнопку "Завершить". Будет создан новый файл клиента шаблона `greeting.xhtml`, который откроется в редакторе.
. Проверьте разметку. Обратите внимание на содержимое, выделенное *полужирным шрифтом*.
[source,xml]
----
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<body>
<ui:composition *template="./template.xhtml"*>
<ui:define *name="title"*>
title
</ui:define>
<ui:define *name="box"*>
box
</ui:define>
</ui:composition>
</body>
</html>
----
Файл клиента шаблона ссылается на шаблон с помощью атрибута `template` тега `<ui:composition>`. Поскольку шаблон содержит теги `<ui:insert>` для `title` и `box`, клиент шаблона содержит теги `<ui:define>` для этих двух имен. Содержимое, указываемое в тегах `<ui:define>`, - это содержимое, вставляемое в шаблон в тегах `<ui:insert>` соответствующего имени.
. Укажите `greeting` в качестве заголовка файла. Внесите следующее изменение, выделенное *полужирным шрифтом*.
[source,xml]
----
<ui:define name="title">
*Greeting*
</ui:define>
----
. Перейдите к файлу `index.xhtml` (нажмите CTRL+TAB) и скопируйте содержимое, которое обычно появляется в сером квадрате, выведенном на визуализируемой странице. Затем обратно переключитесь на файл `greeting.xhtml` и вставьте его в файл клиента шаблона. (Изменения *выделены полужирным шрифтом*.)
[source,xml]
----
<ui:define name="box">
*<h4>Hi, my name is Duke!</h4>
<h5>I'm thinking of a number
<br/>
between
<span class="highlight">0</span> and
<span class="highlight">10</span>.</h5>
<h5>Can you guess it?</h5>
<h:form>
<h:inputText size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
<h:commandButton id="submit" value="submit" action="response" />
</h:form>*
</ui:define>
----
. Объявите библиотеку тегов HTML JSF для файла. Установите курсор на один из тегов, помеченных флагом ошибки (любой тег с префиксом "`h`"), и нажмите сочетание клавиш CTRL+ПРОБЕЛ. Затем выберите тег из списка предложений автозавершения кодов. Пространство имен библиотеки тегов добавляется к тегу `<html>` файла (выделено ниже *полужирным шрифтом*), и указания на ошибки исчезают.
[source,java]
----
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
*xmlns:h="http://xmlns.jcp.org/jsf/html"*>
----
При установке курсора после "`m`" в `<h:form>` и нажатии сочетания клавиш CTRL+ПРОБЕЛ к файлу автоматически добавляется пространство имен. Если при нажатии сочетания клавиш CTRL+ПРОБЕЛ доступен только один логический параметр, он немедленно применяется к файлу. Библиотека тегов JSF автоматически объявляется при вызове автозавершения кода в тегах.
==== response.xhtml
Поскольку проект уже содержит файл с именем `response.xhtml` и известно, как теперь должен выглядеть файл клиента шаблона, измените существующий файл `response.xhtml`, чтобы получить соответствующий файл клиента шаблона. (В целях данного руководства просто скопируйте и вставьте предоставленный код.)
1. Откройте файл `response.xhtml` в редакторе. (Если он уже открыт, нажмите CTRL+TAB и выберите его). Замените содержимое всего файла нижеприведенным кодом.
[source,xml]
----
<?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://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<body>
<ui:composition template="./template.xhtml">
<ui:define name="title">
Response
</ui:define>
<ui:define name="box">
<h4><h:outputText escape="false" value="#{UserNumberBean.response}"/></h4>
<h:form prependId="false">
<h:commandButton id="backButton" value="Back" action="greeting" />
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
----
Обратите внимание на то, что файл идентичен файлу `greeting.xhtml`, за исключением содержимого, указанного в тегах `<ui:define>` для `title` и `box`.
. В дескрипторе развертывания `web.xml` проекта измените запись файла приветствия таким образом, чтобы при запуске приложения открывалась страница, представленная файлом `greeting.xhtml`.
В окне 'Проекты' дважды щелкните 'Файлы конфигурации' > `web.xml`, чтобы открыть его в редакторе. На вкладке "Страницы" измените поле "Файлы приветствия" на `faces/greeting.xhtml`.
image::images/welcome-files.png[title="Измените запись 'Файлы приветствия' в дескрипторе развертывания"]
. Выполните проект и посмотрите, как он выглядит в браузере. Нажмите F6 (fn-F6 в Mac) или нажмите кнопку 'Запустить проект'( image:images/run-project-btn.png[] ) на главной панели инструментов. Проект будет развернут на сервере GlassFish и открыт в браузере.
При использовании шаблона Facelets и файлов клиента шаблона поведение приложения не меняется. Выделив повторяющийся код на страницах приветствия и ответа приложения, можно уменьшить размер приложения и устранить возможность написания повторяющегося кода, если впоследствии будут добавляться другие страницы. Это позволяет сделать разработку более эффективной и упростить управление при работе с большими проектами.
link:/about/contact_form.html?to=3&subject=Feedback:%20Introduction%20to%20JSF%202.0[+Отправить отзыв по этому учебному курсу+]
[[seealso]]
== Дополнительные сведения
Подробнее о JSF 2.x см. в следующих ресурсах.
=== Статьи и учебные курсы по NetBeans
* link:jsf20-support.html[+Поддержка JSF 2.x в IDE NetBeans+]
* link:jsf20-crud.html[+Создание приложения JavaServer Faces 2.x CRUD на основе базы данных+]
* link:../../samples/scrum-toys.html[+Scrum Toys – полный пример приложения JSF 2.0+]
* link:../javaee/javaee-gettingstarted.html[+Начало работы с приложениями Java EE+]
* link:../../trails/java-ee.html[+Учебная карта по Java EE и Java Web+]
=== Внешние ресурсы
* link:http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[+Технология JavaServer Faces+] (официальная домашняя страница)
* link:http://jcp.org/aboutJava/communityprocess/final/jsr314/index.html[+Спецификация JSR 314 для JavaServer Faces 2.0+]
* link:http://docs.oracle.com/javaee/7/tutorial/doc/jsf-develop.htm[+Учебный курс по Java EE 7. Глава 12. Разработка по технологии JavaServer Faces+]
* link:http://javaserverfaces.dev.java.net/[+GlassFish Project Mojarra+] (официальный пример реализации JSF 2.х)
* link:http://forums.oracle.com/forums/forum.jspa?forumID=982[+Интернет-форум OTN: JavaServer Faces+]
* link:http://www.jsfcentral.com/[+JSF Central+]
=== Блоги
* link:http://www.java.net/blogs/edburns/[+Эд Бернс (Ed Burns)+]
* link:http://www.java.net/blogs/driscoll/[+Джим Дрисколл (Jim Driscoll)+]