深入了解JSF(二):從JSF的Lifecycle看JSF對頁面的處理機制和流程
FacesServlet,Lifecycle,Component(組件), BackingBean,JSP是JSF整個框架中的支柱,Component的作用尤為重要。而JSF把JSF生命周期分成6個階段并讓其各司其職,本 文從JSF生命周期的角度全面剖析了JSF對頁面處理的機制和流程。
在上一篇文章:[深入了解JSF]里,我們比較全面地介紹了JSF。這里,為了加深對JSF的認識,本文,我們從JSF對頁面的處理機制和流程方面對JSF做一下再認識。
基本上,JSF根據不同的用戶請求(user request)而做了不同的處理:
1, 頁面顯示請求:頁面初始化。第一次顯示該頁面時(session單位)。
2, 事件處理請求:用戶按下了命令按鈕或命令聯(lián)結,需要JSF加以處理。
下面分別加以介紹。
頁面初始化時
1, 用戶請求某JSF頁面2, 由WEB服務器(SERVLET/JSP容器)接受請求,交由FacesServlet.service()處理
3, 因為是第一次顯示該頁面,直接通過LifecleImpl.render重畫畫面。
4, 畫面重畫時調用JspViewHandlerImpl.renderView,實際上通過 RequestDispacher.forward/redirect調用編譯好的JSP代碼。此時,如果被調用的JSP還未被編譯或者該jsp文件被修 改過的情況,會先對jsp文件進行編譯后再調用。
5, JSP代碼的執(zhí)行: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組件數(shù),不能重載視圖的話,JSF則認為該頁面為當前用戶第一次請求,直接跳轉到renderView(畫面重畫階段)對畫面進行重畫。
2, ApplyRequestValuesPhase(應用請求值階段):
這一階段主要把從瀏覽器過來的數(shù)據反映到對應的組件里。也可以看作為數(shù)據綁定。另外,這一階段還做了一個很重要的處理。事件(EVENT)的隊列入隊處理(queueEvent),此處被加入隊列中的消息事件將在第5個階段被加以處理。
主 要調用過程:Lifecycle.execute() -> ApplyRequestValuesPhase.execute() -> Component.processDecodes() -> Component.decode() -> Component.valueBinding -> Renderer.decode() -> Component.queueEvent()
3, ProcessValidationsPhase(合法性檢查階段)
此階段對數(shù)據進行合法性檢查。檢查有錯誤的情況下,跳轉到畫面重畫階段對畫面進行重畫。
主 要調用過程: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(用戶應用程序處理/事件處理階段):
這階段主要調用用戶的應用程序的事件處理方法,對真正的業(yè)務邏輯加以處理。它是JSF和用戶程序進行接口的部分。
主 要調用過程:Lifecycle.execute() -> InvokeApplicationPhase.execute() -> >UIViewRoot.processApplication->HtmlCommandButton.broadcast->ActionListenerImpl.processAction – MethodBinding(#{beanName.methodName})--> BackingBean.eventMethod
6, render(頁面重畫階段):同頁面初始化的頁面重畫處理。上面說的很清楚,這里不做重復了。