圖1 :JSF 的生命周期 


 
      通過上圖可以觀察到,任何一個 JSF“Faces Request” 請求,經(jīng)過 Restore View 、 Apply Request Values 、 Process Validations 、 Update Models 、 Invoke Application 等階段以后,產(chǎn)生了一個 “Render Response” 返回給客戶端。那么,常規(guī) JSF 引擎是如何實現(xiàn)上述過程的呢?   
  



    圖2 :常規(guī) JSF 引擎的請求與響應過程 
   


    回顧一下常規(guī) JSF 引擎針對請求與響應的過程:首先,客戶端請求某個資源,產(chǎn)生一個 Faces Request ;服務器端接收到此請求以后,經(jīng)過一系列后臺處理,產(chǎn)生一個 Faces Response 。我們注意到:響應的 Content-Type 是 text/html ,而產(chǎn)生的內(nèi)容主體是一段 HTML 文本;瀏覽器在接收到 HTML 文本以后,進行整個頁面的渲染與刷新。
  
      無需寫 Ajax 代碼的 Ajax Enabled 應用
  
       我用自己開發(fā)的 JSF 引擎,這樣處理上述過程(詳見參考資料 www.OperaMasks.org ),如下圖所示:   



  
  圖 3 : OperaMasks JSF 實現(xiàn)的請求與響應過程 
  


      首先可以觀察到, Faces Request 的發(fā)出是基于 “x-requested-by: XML Http Request” ,也就是說,這是一個 Ajax 請求,而該請求在到達服務器端以后,服務器端所產(chǎn)生的 Faces Response 同常規(guī) Faces Response 相比也發(fā)生了變化: Content-Type 不再是 text/html ,變成了 text/javascript ;并且,響應的主體也不再是 html 文本,而是一堆 script 腳本。瀏覽器在接收到響應以后,再也不需要進行整個頁面的渲染與刷新,而只僅僅需要執(zhí)行這段腳本內(nèi)容,將頁面的控件進行更新即可。
  
      顯而易見,通過上述 JSF 技術,我們獲得了:
  
      基于 Ajax 的請求、應答、及頁面控件的更新
      數(shù)據(jù)傳輸量明顯減少
      避免整個頁面的刷新,更好的用戶體驗
      系統(tǒng)保持敏捷、高效
  
     換言之:任何標準 JSF 應用,只需將其在 OperaMasks JSF 引擎上運行,就可以達到這樣的效果。我們并沒有寫任何一行 Ajax 的代碼,但是,我們的應用卻是自然而然的 Ajax Enabled 的應用。大道至簡,大象無形。
  
     奧妙所在: JSF 的 Render 機制
  
     為什么可以這樣?
  
   JSF 組件只是特定狀態(tài)和行為的載體,而組件以什么形式去和用戶交互,是完全可定制的、獨立于該特定的表現(xiàn)語言,可以是 HTML 、 WML 或者其他形式;具體是什么,可以通過指定 JSF 組件的 Render Kit 來實現(xiàn),而每一種 Render Kit ,對應于組件作者寫的同一風格和形式的一系列 Render 。
  
   比如,如果想在網(wǎng)頁中實現(xiàn)圖表功能( Chart) , MSIE 有 VML , Gecko 和 Opera 有 SVG ;而在服務器端只需要簡單地判斷一下瀏覽器類型,就可以選擇一個 Render Kit ,生成不同的客戶端表現(xiàn)來完成相同功能?D?D這是用常規(guī) JSP 技術很難完成的任務。
  
   通俗的說, JSF 組件可以翻譯成任何你想要的形式。 So , JSF 框架比現(xiàn)有其它開源框架具有更強的生命力。上文所述的 OperaMasks JSF ,其容器級別 Ajax 實現(xiàn),正是靈活應用 Render Kit 的具體案例。
  
      從容器級別對 Ajax 予以支持的 JSF 引擎
  
   我們提出的 JSF 是直接由 JSF 容器來處理 Ajax 請求的,它會根據(jù)請求類型來判斷這是一個正常 HTTP 請求還是一個 Ajax 請求:如果是常規(guī) HTTP 請求就運行 JSP 頁面,生成頁面文檔(特定的,對于 Ajax Render kit ,要加入一些 Ajax 基礎 JavaScript 代碼);如果是 Ajax 請求,服務器對請求參數(shù)正常解碼,并執(zhí)行 JSF 中除頁面輸出階段以外的所有其他階段,生成一個 JSF 組件樹。
  
   一直到這一步為止,處理方式與對普通 HTTP 請求的處理完全一致,唯一不同的是:在隨后 Render Response 階段,容器除了調(diào)用組件作者寫的 Ajax 功能 Renderer 以外,更重要的是在生成響應頁面時,會過濾掉一切不會變化的靜態(tài)內(nèi)容?D?D也就是說,靜態(tài)內(nèi)容不會生成到響應頁面中去,而對每一個動態(tài)內(nèi)容則會生成一個相應 JavaScript 代碼(可以更進一步優(yōu)化為只有變化了的動態(tài)內(nèi)容才處理)。這樣,傳給客戶的 Ajax 應答實際上是由這樣一些 JavaScript 語句構成。在 Ajax 響應返回到客戶端時,就可以自動由 Ajax 回調(diào)函數(shù)執(zhí)行這些 JavaScript 語句,完成對頁面即時的、局部的更改,而不需要刷新整個頁面。依賴 JSF 組件的具體功能,甚至可以改變頁面的外觀。而整個 Ajax 機制由 JSF 引擎提供,對用戶完全透明。
  
   實際上,在 JSF 規(guī)范中 JSF 頁面輸出階段所采用的 Render Kit 是可替換的,默認的 HTML_BASIC Render Kit 輸出的是標準 HTML 語法,不包含任何 Java Script 代碼。我們提出的 JSF 引擎實現(xiàn)了一個 Ajax Render Kit ,可以在 HTML 文檔中嵌入 Java Script 代碼來實現(xiàn) Ajax 特性,而替換 Render Kit 只需要修改配置文件即可。
  
   簡單地說,這種 JSF 引擎為每個標準組件都實現(xiàn)了相應的 Ajax Render , 比如對 UICommand 組件,其 Ajax Render 會在 onclick 事件中加入 JavaScript 的 Ajax 提交代碼,向服務器提交 Ajax 請求。通過這種方式,任何一個包含標準 JSF 組件的 Web 應用,都可以通過只更改 Render Kit 配置為 Ajax 來實現(xiàn) Web 應用 Ajax 化。而對于第三方的組件,可能本身并不支持 Ajax ,但使用一個名為 的標簽,就可以立即將這個第三方組件轉換成 Ajax Enabled 。
  
   例如, Apache myfaces 的 Tomahawk 項目提供了一個 Tree 組件,這個組件本身并不支持 Ajax ,每當按下一個 Tree 結點都將重新刷新整個頁面。使用 標簽后,則只刷新 Tree 部分,而不刷新頁面的其他部分。當然更好的方式是,提供一個本身就支持 Ajax 的 Tree 組件,以減少冗余數(shù)據(jù)的傳遞。關于 標簽的原理,有興趣的讀者可以參考 OperaMasks JSF 的源碼(詳見參考資料),這里就不再一一贅述了。
  
   綜上, JavaEE 需要 Ajax ,但并不需要傳統(tǒng)的 Ajax 開發(fā)模式。通過我們提出的 OperaMasks JSF 技術,我們不再需要知道什么是 Ajax ,而我們的應用卻是自然而然的 Ajax Enabled 應用。
  
   因此,我們認為: JavaEE Without Ajax !

分享到

多易

相關推薦