FacesServlet,Lifecycle,Component(组 件),BackingBean,JSP是JSF整个框架中的支柱,Component的作用尤为重要。而JSF把JSF生命周期分成6个阶段并让其各司其 职,本文从JSF生命周期的角度全面剖析了JSF对页面处理的机制和流程。



在上一篇文章:[深入了解JSF(一)]里,我们比较全面地介绍了JSF。这里,为了加深对JSF的认识,本文,我们从JSF对页面的处理机制和流程方面对JSF做一下再认识。

基本上,JSF根据不同的用户请求(user request)而做了不同的处理:
1,    页面显示请求:页面初始化。第一次显示该页面时(session单位)。
2,    事件处理请求:用户按下了命令按钮或命令联结,需要JSF加以处理。


下面分别加以介绍。

页面初始化时

1,    用户请求某JSF页面


2,    由WEB服务器(SERVLET/JSP容器)接受请求,交由FacesServlet.service()处理


3,    因为是第一次显示该页面,直接通过LifecleImpl.render重画画面。


4,    画 面重画时调用JspViewHandlerImpl.renderView,实际上通过 RequestDispacher.forward/redirect调用编译好的JSP代码。此时,如果被调用的JSP还未被编译或者该jsp文件被修 改过的情况,会先对jsp文件进行编译后再调用。


5,    JSP代码的执行:JSP里,如果是一般的HTML标签和文本,则直接加以输出;如 果是标签(Tag),则 为Tag生成相应的instance,分别调用Tag.doStartTag/doEndTag等进行描画(生成HTML形式的输出)。当然特殊的情况, 如h:inputText等JSF标签,基本处理完全跟其他JSP TAG一样,但JSF标签,分成了三部分:标签(Tag),组件(Component),和描画器(Renderer),处理时把一般JSP标签里做的工 作分散到了三部分。


6,    JSF标签的描画:上面提到,JSF标签的描画也跟一般JSP标签的描画一样,不过JSF标签有专门的描画器(Renderer),一般来说,标准的JSF标签的描画过程为:


Tag.doStartTag > Component.encodeBegin > Renderer.encodeBegin >  Tag .encodeChildren > Component.encodeChildren > Renderer.encodeChildren > Tag.doEndTag > Component.encodeEnd > Renderer.encodeEnd


也就是说,JSF标签的Tag,Component只是起了一个调用作用,真正地描画工作是在Renderer里完成的。


7,    页面初始化完成。画面显示。



按钮事件处理时

JSF 对事件的处理就复杂多了。JSF把整个事件处理分成6个阶段:restoreView,applyRequestValuesPhase, processValidations, updateModelValues, invokeApplication,renderView。每个阶段完成不同的处理。其中,restoreView阶段和renderView阶段的处 理跟

页面初始化时完全一样。



下面详细介绍一下各阶段的处理流程:


1,    RestoreViewPhase(重载视图阶段):


如名所述,这一阶段重载画面的视图结构。首先试图从session,或cookie里还原JSF组件数,不能重载视图的话,JSF则认为该页面为当前用户第一次请求,直接跳转到renderView(画面重画阶段)对画面进行重画。


2,    ApplyRequestValuesPhase(应用请求值阶段):


这一阶段主要把从浏览器过来的数据反映到对应的组件里。也可以看作为数据绑定。另外,这一阶段还做了一个很重要的处理。事件(EVENT)的队列入队处理(queueEvent),此处被加入队列中的消息事件将在第5个阶段被加以处理。


主 要调用过程:Lifecycle.execute() -> ApplyRequestValuesPhase.execute() -> Component.processDecodes() -> Component.decode() -> Component.valueBinding -> Renderer.decode() -> Component.queueEvent()


3,    ProcessValidationsPhase(合法性检查阶段)


此阶段对数据进行合法性检查。检查有错误的情况下,跳转到画面重画阶段对画面进行重画。


主 要调用过程:Lifecycle.execute() -> ProcessValidationsPhase .execute() -> UIViewRoot.processValidators()->HtmlForm.processValidators()->UIInput.validate() -> Validators.validate()


4,    UpdateModelValuesPhase(更新模型值阶段):


此阶段把经过变换(CONVERTER变换等)后的组件里值反映到BackingBean里。


主 要调用过程:Lifecycle.execute() -> UpdateModelValuesPhase.execute() -> UIViewRoot.processUpdates->HtmlForm.processUpdates->UIInput.processUpdates -> UIInput.updateModel –ValueBinding (#{beanName.propertyName}) BackingBean


5,    InvokeApplicationPhase(用户应用程序处理/事件处理阶段):


这阶段主要调用用户的应用程序的事件处理方法,对真正的业务逻辑加以处理。它是JSF和用户程序进行接口的部分。


主 要调用过程:Lifecycle.execute() -> InvokeApplicationPhase.execute() -> >UIViewRoot.processApplication->HtmlCommandButton.broadcast->ActionListenerImpl.processAction – MethodBinding(#{beanName.methodName})--> BackingBean.eventMethod


6,    render(页面重画阶段):同页面初始化的页面重画处理。上面说的很清楚,这里不做重复了。