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 можно нарваться на исключительную ситуацию. |