在上一篇文章:[深入了解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(頁面重畫階段):同頁面初始化的頁面重畫處理。上面說的很清楚,這里不做重復了。