看了core JSF里詳細描述的JSF的生命周期,基本上可以劃分為六個(gè)周期.
1:Restore View(恢復視圖)
所謂的視圖也就是一些基本的GUI組件.也就是常說(shuō)的HTML控件吧.視圖一般來(lái)說(shuō)分為三種實(shí)例:新視圖,原始視圖,后視圖三種.所謂的新視圖就是你第一次請求所呈現給你的.而原始視圖也就是你已經(jīng)進(jìn)入了這個(gè)頁(yè)面.只是刷原有頁(yè)面.而后視圖呢也就是你點(diǎn)后退按鈕回到的那個(gè)頁(yè)面.(它只負責從恢復內容,不刷新內容.)Restore View phase recreates the server-side component tree when you revisit a JSF page.
2;Apply Request Values(應用請求值)
在這階段主要數據接收.SUN在自己出版的core JSF中是這樣說(shuō)的.The Apply Request Values phase copies request parameters into component submitted values.
3:Process Validations(執行驗證)
根據接收到的數據進(jìn)行轉換驗證.The Process Validations phase first converts those submitted values and validates the converted value.
4:Update Model Values(更新模型)
開(kāi)始給控件賦新值.The Update Model Values phase copies (converted and validated) values to the model, which is typically denoted in JSF pages with value reference expressions
5:Invoke Application(調用程序)
這個(gè)階段主要進(jìn)行actionListener 和 action 處理.先調用ActionListener 然后再進(jìn)行Action 操作.The Invoke Application phase invokes action listeners and actions, in that order, for command components.
6:Render Respose(進(jìn)行響應)
返回一個(gè)新的請求視圖.the Render Response phase saves state and loads the next view.從下圖你能清楚的知道JSF的六個(gè)生命周期是如何的運行的. 
在下面的測試中,你需要對faces-config.xml: 進(jìn)行如下的設置:
<lifecycle>
<phase-listener>net.emlog.fei.PhaseEventListener</phase-listener>
</lifecycle>
在實(shí)現生命周期的監聽(tīng)的時(shí)候,你需要編寫(xiě)一個(gè)生命監聽(tīng)的類(lèi).PhaseEventListener他實(shí)現了javax.faces.event.PhaseListener接口.在這個(gè)接口中,需要實(shí)現這兩具方法beforePhase(PhaseEvent e)和afterPhase(PhaseEvent e).需進(jìn)行后臺的bean則顯得簡(jiǎn)單.
大體的,你可以根據以下幾個(gè)值來(lái)更改生命周期的執行.(1).immediate="true"(2)調用FacesContext.renderResponse()(3):調用FacesContext.responseComplete()這三者是有一定的區別的.
正常運行的情況下,它的生命周期是這樣進(jìn)行的:
開(kāi)始調用 APPLY_REQUEST_VALUES 2事件.
然后,APPLY_REQUEST_VALUES 2事件響應了
開(kāi)始調用 PROCESS_VALIDATIONS 3事件.
在getInput方法中得到input值為123
值改變事件發(fā)生,開(kāi)始設置input值為1
在setInput方法中設置input值為1
在setOutput方法中設置output值為1
然后,PROCESS_VALIDATIONS 3事件響應了
如下面的代碼片段:(沒(méi)有使用局部刷新)
<h:form id="form">
<h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}"
immediate="true" onchange="submit()">
</h:inputText>
<h:outputText id="abs" value="#{vcl.output}"></h:outputText>
</h:form>
public void changeAction(ValueChangeEvent vc){
/**
* FacesContext fc = FacesContext.getCurrentInstance();
UIViewRoot root = fc.getViewRoot();
String locale = vc.getNewValue().toString();
root.setLocale(new Locale(locale));
*/
String string = vc.getNewValue().toString();
System.out.println("值改變事件發(fā)生,開(kāi)始設置input值為" + string);
setInput(string);
setOutput(string);
FacesContext fc = FacesContext.getCurrentInstance();
//fc.responseComplete();
//fc.renderResponse();
}
上面的方法中,由于將immediate設為true,所以它會(huì )將
開(kāi)始調用 APPLY_REQUEST_VALUES 2事件.
在getInput方法中得到input值為123
值改變事件發(fā)生,開(kāi)始設置input值為1
在setInput方法中設置input值為1
在setOutput方法中設置output值為1
然后,APPLY_REQUEST_VALUES 2事件響應了
開(kāi)始調用 PROCESS_VALIDATIONS 3事件.
然后,PROCESS_VALIDATIONS 3事件響應了.
僅僅將immediate設置為true用戶(hù)不大的.因為最后他還是要走完所有的六個(gè)生命周期.我們結合FacesContext.renderResponse() 和FacesContext.responseComplete()來(lái)看看他們有什么區別.
FacesContext.responseComplete()情況:
開(kāi)始調用 APPLY_REQUEST_VALUES 2事件.
在getInput方法中得到input值為123
值改變事件發(fā)生,開(kāi)始設置input值為1
在setInput方法中設置input值為1
在setOutput方法中設置output值為1
然后,APPLY_REQUEST_VALUES 2事件響應了(后面沒(méi)了,它甚至不會(huì )Render Response)所以你會(huì )看到一個(gè)空白的頁(yè)面.
FacesContext.renderResponse() 情況就不同啦:
開(kāi)始調用 APPLY_REQUEST_VALUES 2事件.
在getInput方法中得到input值為123
值改變事件發(fā)生,開(kāi)始設置input值為1
在setInput方法中設置input值為1
在setOutput方法中設置output值為1
然后,APPLY_REQUEST_VALUES 2事件響應了
開(kāi)始調用 RENDER_RESPONSE 6事件.
在getOutput方法中得到output值為1
然后,RENDER_RESPONSE 6事件響應了(相對于responseComplete()他進(jìn)行了Render Response操作.)OK.希望說(shuō)到這你能對所謂的六大生命周期有一個(gè)簡(jiǎn)單的認識.如何我們只是進(jìn)行一次簡(jiǎn)單的WEB開(kāi)發(fā)的話(huà),那么,關(guān)注3,5兩個(gè)階段的實(shí)現就可,如果需要自己編寫(xiě)UI,則需要對生命周期有一個(gè)清楚的認識.也許,從下面的圖你能看得更加的清楚.
當然,我們的重點(diǎn)還是在于局部刷新.AJAX是一個(gè)時(shí)下比較時(shí)興的技術(shù).局部刷新有很多的好處,在此不在細說(shuō).在上面的例子里,我們需要實(shí)現在輸入框里的值改變后,輸入框的值也隨著(zhù)改變.但是我們調用的卻是全局刷新.使用submit()事件來(lái)實(shí)現.接下來(lái)我們就來(lái)看看如何使用AJAX來(lái)實(shí)現局部刷新,以及局部刷的一些細節問(wèn)題.如下代碼段:具體的richfaces請參見(jiàn) http://labs.jboss.com/jbossrichfaces/此處不細說(shuō)配置.
<h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}">
<a4j:support event="onchange" limitToList="true" reRender="input,abs"/>
</h:inputText>
<h:outputText id="abs" value="#{vcl.output}"></h:outputText>
OK.運行代碼后,我們發(fā)現結果是這樣的:
開(kāi)始調用 APPLY_REQUEST_VALUES 2事件.
在getInput方法中得到input值為123
值改變事件發(fā)生,開(kāi)始設置input值為1
在setInput方法中設置input值為1
在setOutput方法中設置output值為1
然后,APPLY_REQUEST_VALUES 2事件響應了
開(kāi)始調用 RENDER_RESPONSE 6事件.
在getOutput方法中得到output值為1
然后,RENDER_RESPONSE 6事件響應了
在應用值及進(jìn)行響應階段我們只是對output進(jìn)行了響應.雖然在reRender設置了兩個(gè)響應目標.但實(shí)現上如你所現,真正響應的只是output控件的get方法.同樣的,在值改變事件前,也只是對input控件進(jìn)行了get響應.這兩個(gè)很重要.這也就是說(shuō).如果在兩個(gè)都為input控件的時(shí)候,事件就有點(diǎn)復雜.因為set事件 他所取的時(shí)input = string 參數string是取決于你顯示出來(lái)給用戶(hù)的.正因為如何,當兩個(gè)事件都進(jìn)行響應的時(shí)候,兩個(gè)輸入控件的值是不一樣的.在同為input的時(shí)候,我們需要加上<a4j:region>在開(kāi)發(fā)文件中的定義是這樣的:The <a4j:region> component defines an area that is decoded on the server after Ajax submission.當然.在有兩個(gè)input控件的情況下,你需要按照以下形式編寫(xiě).
<a4j:region>
<h:inputText id="input" value="#{vcl.input}" valueChangeListener="#{vcl.changeAction}">
<a4j:support event="onchange" limitToList="true" reRender="input,abs"/>
</h:inputText>
</a4j:region>
<h:inputText id="abs" value="#{vcl.output}"></h:inputText>
這樣我們就能保證在進(jìn)行局部刷新提交的時(shí)候,不會(huì )將后一個(gè)input的值也提交上去,從而實(shí)現同時(shí)改變的功能.希望說(shuō)到這你能明白些什么.生命周期的運行是這樣的:在有事件響應的時(shí)候,只會(huì )有輸入控件的get方法.在返回響應的時(shí)候,只會(huì )調用輸出控件的set方法.嗯,就是這樣的.
OK.基本上完畢了.還記得開(kāi)始時(shí)說(shuō)的那個(gè)恢復視圖里的后視圖嗎?這個(gè)東西他是不刷新的.如果我在后面修改了怎么辦呢,返回來(lái)的結果并不會(huì )在后視圖里顯示出來(lái).有兩種方法,一種是頁(yè)面不緩存...另一種則是載入頁(yè)面的時(shí)候進(jìn)行刷新.我選擇了第二種.第一種有點(diǎn)不有好...不過(guò)對于一些很重要的權限控制還是用第一種吧.第二種的處理方法是在頁(yè)面的load事件里加上javascript的刷新頁(yè)面代碼.經(jīng)測試,下面這個(gè)代碼是可行的.
function refresh(){ if(self.name != "index.faces"){
self.name = "index.faces";
self.location.reload();
}
else{
self.name = "";
}
}
但是如何在你的第一個(gè)頁(yè)面里也有第二個(gè)頁(yè)面的功能.則第二個(gè)頁(yè)面的功能在第一個(gè)頁(yè)面功能被使用后不再有效.這個(gè)是由jsf的生命周期決定的.沒(méi)有找到什么好方法來(lái)解決.下圖為JSF與AJAX在一起的處理流程.
聯(lián)系客服