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(页面重画阶段):同页面初始化的页面重画处理。上面说的很清楚,这里不做重复了。