410013796724260
• Webmoney
R335386147728
Z369087728698
Жизненный циклПри поступлении от клиента (браузера) запроса необходимо выполнить определенную последовательность действий, связанную с анализом параметров запроса и, при необходимости, подготовить ответ. При использовании в WEB приложении фреймворков типа Struts, JSF жизненный цикл фреймворка выполняет все необходимые действия, которые пришлось бы делать программисту. Жизненный цикл JSF управляет входными параметрами запроса от клиента, UI-компонентами и синхронизирует их с отображаемой на клиентской стороне странице, т.е. в окне браузера. Также он обрабатывает запросы со стороны клиента на предоставлении изображений, стилей CSS, скриптов и т.п., что необходимо браузеру для правильного представления страницы. При запуске приложения JSF 2 контейнер приложения загружает классы директории WEB-INF/classes, указанные в конфигурационном файле faces-config.xml. Для каждого класса устанавливается время жизни. Варианты времени жизни managed bean компонентов определяются либо в файле конфигурации faces-config.xml, либо при помощи аннотаций согласно принятому соглашению:
Этапы жизненного циклаЖизненный цикл запроса-ответа проходит несколько этапов :
Схематично этапы жизненного цикла обработки запроса в JSF показаны на следующем рисунке. Сплошной линией отображен основной поток выполнения. Пунктирной линией - альтернативный поток, который зависит от атрибутов компонентов, ошибок конвертации или проверок.
Фазы жизненного цикла
Страница Java Server Faces представлена в виде дерева компонентов. Корневым компонентом дерева является UIViewRoot. Фаза жизненного цикла Restore ViewВ фазе Restore View фреймворк выполняет следующие действия :
В конце данной фазы свойство viewRoot у FacesContext'а текущего запроса будет содержать сохранённое состояние вида, которое было в предыдущем запросе или новый вид, созданный с помощью ViewHandler#createView() для указанного идентификатора вида. Фаза жизненного цикла Apply Request ValuesНа данном этапе жизненного цикла каждый компонент обновляет своё состояние на основании информации текущего запроса (параметры, заголовки, cookies и т.д.). Фреймворк должен вызвать метод UIViewRoot#processDecodes, который вызовет методы UIComponent#processDecodes для всех компонентов дерева. Для UIInput-компонентов будет выполнено преобразование данных. В процессе декодирования данных запроса компоненты могут вызвать определенные действия :
В конце этой фазы все компоненты, которые реализуют интерфейс EditableValueHolder, будут обновлены в соответствии с данными, переданными в запросе. Если при преобразовании и валидации возникнут ошибки, то с помощью метода FacesContext#addMessage для соответствующих компонентов будут добавлены сообщения, и их свойство valid будет выставлено в false. Если в данной фазе жизненного цикла какой-либо из слушателей событий (event listener) или методов decode() вызвал один из методов
Иначе управление должно перейти к фазе Process Validations. Фаза жизненного цикла Process ValidationsВ фазе Process Validations вызывается метод UIViewRoot#processValidators(), которые для каждого компонента дерева вызывает метод UIComponent#processValidators(). Компоненты с установленным в true свойством immediate уже выполнили свою валидацию на предыдущем шаге. Если на данном этапе жизненного цикла возникнут ошибки преобразования или валидации, то будет вызван метод FacesContext#addMessage для добавления сообщения об ошибке соответствующих компонентов, и их свойство valid будет выставлено в false. Если в данной фазе какой-либо из вызванных методов validate() или слушатель событий (event listener) вызвал один из методов
Иначе управление должно перейти к фазе Update Model Values. Фаза жизненного цикла Update Model ValuesНа данном этапе можно константировать, что параметры запроса корректны, и что локальное значение каждого компонента дерева с корневым элементом UIViewRoot было обновлено. Наступило время обновления данных в модели приложения для подготовки к выполнению событий приложения, которые находятся в очереди. В данной фазе вызывается метод UIViewRoot#processUpdates(), после чего для каждого компонента дерева будут вызваны методы UIComponent#processUpdates(). Обновление модели выполняется в методе updateModel() компонента. В процессе обновления модели в очередь могут быть добавлены события, которые будут будут распространены заинтересованным слушателям событий. На завершающей стадии данного этапа все объекты модели будут обновлены значениями, содержащимися в соответствующих компонентах. Если какой-либо из вызванных методов validate() или слушатель событий (event listener) на данном этапе вызвал один из методов
Иначе управление должно перейти к фазе Invoke Application. Фаза жизненного цикла Invoke ApplicationВсе обновления модели выполнены и оставшиеся события передаются для обработки приложению. Вызывается метод UIViewRoot#processApplication() для обработки событий, у которых определен идентификатор фазы PhaseId.INVOKE_APPLICATION. Перехватить обработку событий можно переопределением ActionListener. Фаза жизненного цикла Render ResponseRender Response - это завершающая фаза жизненного цикла JSF, в которой формируется ответ. Ответ формируется каскадно, как и во всех предыдущих фазах : вызываются методы encodeXX() каждого компонента. Эти методы определяют, как компоненты (точнее, их визуализаторы — renderers) будут отображаться клиенту. Язык разметки ответа может быть любым : HTML, XHTML, XML и т.п. Кроме генерации ответа на данном этапе происходит сохранение текущего состояния вида, обеспечивая возможность его восстановления при последующих обращениях к странице. Таким образом, в фазе Render Response фреймворк выполняет два действия:
По завершении рендеринга конечное состояние вида должно быть сохранено посредством методов класса StateManager. Эта информация о состоянии должна быть доступна при последующем запросе, чтобы ей можно было воспользоваться в фазе Restore View. К фазе Render Response также относится и объединение статического описания страницы («шаблон»), с ее динамическим наполнением. Но это уже связано и с используемыми фреймворками типа Facelets, Tiles. Пример использования простого Phase ListenerПример страницы с подключением к view слушателя lifecycle :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
<f:view beforePhase="#{LifecycelBean.phaseTest}"/>
</h:head>
<h:body>
<h:form>
Hello from Facelets
<h:commandButton value="Submit" id="submit" action="" />
</h:form>
</h:body>
</html>
Листинг managed bean компонента :
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseEvent;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class LifecycelBean
{
public LifecycelBean() {}
public String getMessage(){
return "Hello World!";
}
public void phaseTest(PhaseEvent evt) throws Exception{
try {
if (PhaseId.APPLY_REQUEST_VALUES.equals(evt.getPhaseId())) {
System.out.println("Phase is " + PhaseId.APPLY_REQUEST_VALUES);
}
if (PhaseId.INVOKE_APPLICATION.equals(evt.getPhaseId())) {
System.out.println("Phase is " + PhaseId.INVOKE_APPLICATION);
}
if (PhaseId.RENDER_RESPONSE.equals(evt.getPhaseId())) {
System.out.println("Phase is " + PhaseId.RENDER_RESPONSE);
}
} catch (Exception e) {
System.out.println(e);
}
}
public String actionSubmit() {
System.out.println("Нажатие на кнопку Submit");
return "wellcome.xhtml";
}
}
Результат работы LifecycelBean компонента Phase is RENDER_RESPONSE 6 Phase is RENDER_RESPONSE 6 Phase is RENDER_RESPONSE 6 Phase is APPLY_REQUEST_VALUES 2 Phase is INVOKE_APPLICATION 5 Нажатие на кнопку Submit Phase is RENDER_RESPONSE 6 Использование flash scopeflash scope не используется в чистом виде для определения времени жизни managed bean компонента, а может быть использован для передачи данных один раз между двумя страницами подобно HttpSession. Пример размещения объекта во flash scope :
// Размещение данных во флеш
public String gotoPageQ(final String login) {
User user = DAOFactory.loadUser (login);
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("account", user);
return "pageQ?faces-redirect=true";
}
Чтение данных из flash scope в интерфейсе :
<h:outputLabel value="#{flash['user.email']}" />
// или так
<h:outputLabel value="#{flash['user'].login}" />
Отличие flash scope от сессии заключается в том, что фреймворк JSF сам удаляет из flash scope размещенные в нем объекты. Поэтому, пользоваться данным средством необходимо аккуратно, т.к. при попытке обновления страницы нажатием на клавиши CTRL-F5 можно нарваться на исключительную ситуацию. |
