User Tools

Site Tools


jsf-ru:faq:request_lifecycle

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
jsf-ru:faq:request_lifecycle [2006/01/14 20:47] – добавлено описание фазы Update Model Values slonopotamusjsf-ru:faq:request_lifecycle [2019/06/12 16:08] (current) – external edit 127.0.0.1
Line 2: Line 2:
 ====== JSF Request Lifecycle ====== ====== JSF Request Lifecycle ======
  
-===== В теории ===== 
  
-Как нам подсказывает [[google>jsf request lifecycle|Google]] или та же спецификация по JSF, жизненный цикл JSF-запроса выглядит так: 
  
-{{.:jsf-request-lifecycle.gif}} +===== Big Picture ===== 
- +{{jsf-ru:faq:jsf-lifecycle.gif}}
-И всё бы хорошо, но. Эта модель **не работает**. А конкретно, она не работает тогда, когда к JSF-странице обращаются напрямую по ссылке, а не когда на неё переходят с другой JSF-страницы. В связи с этим, например, приходится жутко извращаться при [[with_jaas|интеграции JSF с JAAS]]. А когда обращаются напрямую, то **все** стадии, помеченные красным (application-level phases), на которых приложению проще всего взаимодействовать с JSF, **пропускаются**. Вас это радует? Меня это откровенно бесит.+
  
 ===== Описание стадий ===== ===== Описание стадий =====
Line 49: Line 46:
  
 Если какой-либо из вызванных методов ''decode()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#responseComplete()|FacesContext#responseComplete()]], то обработка текущего запроса должна быть немедленно прекращена. Если какой-либо из вызванных методов ''decode()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#renderResponse()|FacesContext#renderResponse()]], то управление должно немедленно перейти к фазе [[#render.response|Render Response]]. Иначе управление должно перейти к фазе [[#process.validations|Process Validations]]. Если какой-либо из вызванных методов ''decode()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#responseComplete()|FacesContext#responseComplete()]], то обработка текущего запроса должна быть немедленно прекращена. Если какой-либо из вызванных методов ''decode()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#renderResponse()|FacesContext#renderResponse()]], то управление должно немедленно перейти к фазе [[#render.response|Render Response]]. Иначе управление должно перейти к фазе [[#process.validations|Process Validations]].
 +
  
  
  
 ==== Process Validations ==== ==== Process Validations ====
-В процессе создания вида (''view'') для текущего запроса, к компонентам могут быть добавлены [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/validator/Validator.html|валидаторы]]. Помимо этого, компоненты могут сами реализовывать логику валидации в их методах ''validate()''((Найти явадок.))((Внимание! В следующей версии JSF этот метод будет помечен как ''deprecated'', поэтому избегайте его использования.)).+В процессе создания вида (''view'') для текущего запроса, к компонентам могут быть добавлены [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/validator/Validator.html|валидаторы]]. Помимо этого, компоненты могут сами реализовывать логику валидации в их методах ''validate()''((Найти явадок.)).
  
 На стадии [[#process.validations|Process Validations]] жизненного цикла запроса реализация JSF должна вызвать метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIViewRoot.html#processValidators(javax.faces.context.FacesContext)|UIViewRoot#processValidators()]]. По-нормальному это повлечёт за собой рекурсивный вызов метода [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponent.html#processValidators(javax.faces.context.FacesContext)|UIComponent#processValidators()]] для каждого компонента в дереве компонентов, как написано в документации к этому методу. Обратите внимание, что компоненты, реализующие [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/EditableValueHolder.html|EditableValueHolder]], у которых свойство ''immediate'' выставлено в ''true'', уже выполнили свою валидацию на стадии [[#apply.request.values|Apply Request Values]]. На стадии [[#process.validations|Process Validations]] жизненного цикла запроса реализация JSF должна вызвать метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIViewRoot.html#processValidators(javax.faces.context.FacesContext)|UIViewRoot#processValidators()]]. По-нормальному это повлечёт за собой рекурсивный вызов метода [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponent.html#processValidators(javax.faces.context.FacesContext)|UIComponent#processValidators()]] для каждого компонента в дереве компонентов, как написано в документации к этому методу. Обратите внимание, что компоненты, реализующие [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/EditableValueHolder.html|EditableValueHolder]], у которых свойство ''immediate'' выставлено в ''true'', уже выполнили свою валидацию на стадии [[#apply.request.values|Apply Request Values]].
Line 72: Line 70:
  
 Если какой-либо из вызванных методов ''updateModel()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#responseComplete()|FacesContext#responseComplete()]], то обработка текущего запроса должна быть немедленно прекращена. Если какой-либо из вызванных методов ''updateModel()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#renderResponse()|FacesContext#renderResponse()]], то управление должно немедленно перейти к фазе [[#render.response|Render Response]]. Иначе управление должно перейти к фазе [[#invoke.application|Invoke Application]]. Если какой-либо из вызванных методов ''updateModel()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#responseComplete()|FacesContext#responseComplete()]], то обработка текущего запроса должна быть немедленно прекращена. Если какой-либо из вызванных методов ''updateModel()'' или слушатель событий (//event listener//), который обрабатывал событие, вызвал метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/context/FacesContext.html#renderResponse()|FacesContext#renderResponse()]], то управление должно немедленно перейти к фазе [[#render.response|Render Response]]. Иначе управление должно перейти к фазе [[#invoke.application|Invoke Application]].
 +
  
 ==== Invoke Application ==== ==== Invoke Application ====
-FIXME+Если обрабока запроса дошла до этой стадии, то предполагается, что все обновления модели выполнены и оставшиеся события должны быть переданы приложению. Реализация JSF должна убедиться, что вызван метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIViewRoot.html#processApplication(javax.faces.context.FacesContext)|UIViewRoot#processApplication()]]. По умолчанию этот метод распространяет все события, у которых задан идентификатор фазы [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/event/PhaseId.html#INVOKE_APPLICATION|PhaseId.INVOKE_APPLICATION]]. 
 + 
 +Продвинутые приложения (или фрэймворки) могут заменять ''ActionListener'', вызвав метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/application/Application.html#setActionListener(javax.faces.event.ActionListener)|Application#setActionListener()]] для текущего приложения. Однако реализация JSF должна предоставить ''ActionListener'' по умолчанию, который ведёт себя согласно [[ActionListener|описанию]]. 
 + 
 + 
 ==== Render Response ==== ==== Render Response ====
-FIXME+Эта фаза производит два действия: 
 +  - Выводит результат клиенту 
 +  - Сохраняет состояние результата для последующий запросов. 
 + 
 +Эти две задачи объединены в одну фазу потому, что в JSP-приложениях вывод результата может вызвать построение вида (''view'') по мере того, как выводится страница. Поэтому невозможно сохранить состояние до тех пор пока вид не построен, а состояние необходимо сохранить дотого, как вывод будет отправлен клиенту для того, чтобы сохранить у клиента состояние. 
 + 
 +JSF поддерживает различные подходы, которые реализации JSF могут использовать при создании результата, который соответствует содержимому результирующего вида, включая: 
 +  * Получение всего вывода напрямую из результатов вызова методов ''encode()'' (либо компонентов либо соответствующих рендереров). 
 +  * Чередование результатов энкодинга компонентов с содержимым которое динамически генерируется логикой приложения. 
 +  * Чередование результатов энкодинга компонентов с контентом, который копируется из статического "шаблонного" ресурса. 
 +  * Использование результатов энкодинга компонентов посредством вызовов методов в динамическом ресурсе (именно так отображаются компоненты в виде custom-тэгов в JSP-страницах). 
 + 
 +Из-за большого количества возможных вариантов, механизм реализации фазы [[#render.response|Render Response]] не может быть точно описан. Однако, все реализации этой фазы должны удовлетворять следующим требованиям: 
 +  * Реализация JSF должна предоставить реализацию ''ViewHandler'''а по умолчанию, которая вызывает метод [[http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/RequestDispatcher.html#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)|RequestDispatcher#forward()]] для ресурса, путь (относительно контекста) которого равен идентификатору вида текущего дерева компонентов. 
 +  * Если весь вывод получается из энкодирующих методов компонентов или ассоциированных с ними рендереров, то дерево компонентов должно обходиться в таком же порядке, в каком оно обходилось на более ранних фазах. 
 +  * Если содержимое вывода получается из энкодирующих методов и дополнительных источников, компоненты могут рендериться (мда) в произвольном порядке((Обычно порядок задаётся специальной разметкой (например, JSP-тэгами) в шаблоне, ассоциированном с деревом компонентов.)). 
 +  * В процессе рендеринга дополнительные компоненты могут быть добавлены в дерево компонентов на основании информации, имеющейся у реализации [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/application/ViewHandler.html|ViewHandler]]'а((Например, эта техника используется когда custom-тэги в JSP страницах используются в качестве технологии для рендеринга, как описано в [[jsp_integration|Интеграции с JSP]])). Однако, перед добавлением новых компонентов, реализация ''ViewHandler'''а должна предварительно проверить, не содержится ли уже указанный компонент в дереве компонентов. Если уже содержится (возможно из-за того, что предыдущие фазы создали его заранее), должны использоваться свойства и атрибуты уже существующего компонента((Вот этот момент я плохо понял.)). 
 +  * Ни при каких условиях не должен выбираться компонент для рендеринга, если у какого-либо из его родительских компонентов свойство ''rendersChildren'' установлено в ''true''. В таких случаях тот родительский компонент должен сам рендерить своих детей, когда он будет выбран. 
 +  * Если метод [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponent.html#isRendered()|isRendered()]] у компонента возвращает ''false'', то рендерер для этого компонента не должен производить никакой разметки и никакой из детей или facet'ов этого компонента не должен быть отрендерен. 
 + 
 +Для компонентов, которые реализуют интерфейс [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/ValueHolder.html|ValueHolder]] (например, ''UIInput'' и ''UIOutput''), должно выполняться преобразование данных в соответствии с тем, как это описано в [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIOutput.html|документации]] к ''UIOutput''
 + 
 +По завершении рендеринга, конечное состояние вида должно быть сохранено посредством методов класса [[http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/application/StateManager.html|StateManager]]. Эта информация о состоянии должна быть доступна при последующем запросе, чтобы ей можно было воспользоваться в фазе [[#restore.view|Restore View]]. Более подробная информацию о ''StateManager'''е можно найти [[StateManager|здесь]]. 
 ===== На практике ===== ===== На практике =====
 Делаем простенький [[.:PhaseListener]]: Делаем простенький [[.:PhaseListener]]:
Line 124: Line 151:
  
 Вывод: если вы хотите, чтобы какой-то кусок кода вызывался при каждом обращении к JSF-приложению (например, вы хотите [[.:with_jaas|защитить]] какие-то страницы от просмотра, то необходимо либо писать фильтр, чтобы запросы к JSF-сервлету проходили сначала через него, либо писать [[.:PhaseListener]], который будет висеть на фазе ''RESTORE_VIEW''. Вывод: если вы хотите, чтобы какой-то кусок кода вызывался при каждом обращении к JSF-приложению (например, вы хотите [[.:with_jaas|защитить]] какие-то страницы от просмотра, то необходимо либо писать фильтр, чтобы запросы к JSF-сервлету проходили сначала через него, либо писать [[.:PhaseListener]], который будет висеть на фазе ''RESTORE_VIEW''.
 +
 +
 +===== Ссылки по теме =====
 +  * [[http://www-128.ibm.com/developerworks/java/library/j-jsf2|JSF for nonbelievers: The JSF application lifecycle]] (англ.)
 +
jsf-ru/faq/request_lifecycle.1137271637.txt.gz · Last modified: 2019/06/12 16:12 (external edit)