2 年前, Ajax 開始進(jìn)入人們的視野。時至今日, Ajax 已經(jīng)成為一個紅得發(fā)紫的技術(shù)。但是今天,我想說一句: JavaEE without Ajax 。
Ajax 的“原罪”
Ajax 為什么這樣紅?有人說,是因?yàn)槠鹆藗€好聽易記的名字(比如荷蘭著名的 Ajax 球隊(duì),即阿賈克斯);也有人說,是因?yàn)?Google 全新的 Ajax 應(yīng)用產(chǎn)品給人們帶來的超酷體驗(yàn)(比如偉大的 Google Maps 、 GMail 等)。確實(shí)如此, Ajax 能夠如此流行的最主要原因就是它帶來了更好的用戶體驗(yàn)" title="用戶體驗(yàn)">用戶體驗(yàn),改變了人們對傳統(tǒng) Web 應(yīng)用的不佳印象。
???? 然而,即使 Ajax 的狂熱 Fans 也不得不承認(rèn)的是,從技術(shù)層面上來說, Ajax 并沒有帶來什么新鮮的東西。它本質(zhì)上是一種新瓶裝舊酒的技術(shù),好處是通過 Java Script 與 DHTML 提供了一種異步編程模型,從而使 Web 應(yīng)用給客戶帶來了更好的人機(jī)體驗(yàn)。正如我在去年引起大家爭論的拙文《 Ajax ,只是一種過渡技術(shù)》中表述的: Ajax 解決問題的層面較低?;蛘哒f,它解決問題的方法與手段,很難形成一種可高度抽象的框架級解決方案。并且,正是因?yàn)?Ajax 基于 Java Script ,因此不可避免地帶來了 Java Script 的諸多缺點(diǎn),譬如:
????? - 跨瀏覽器是一場噩夢
????? - 對搜索引擎的支持不好
????? - 干掉了 Back 、 History 等按鈕(盡管我并不認(rèn)為 Back 、 History 是什么好東西)
????? - 開發(fā)與維護(hù)成本過高
要 Java, 不要 Java Script
?We Love Java, Not Java Script 。套用毛澤東的慣用句式就是: “ 要 Java, 不要 Java Script” 。相信很多讀者看完這個標(biāo)題也許會不以為然,但這句話卻代表了許多 J2EE 開發(fā)人員的心聲。
眾多 Java 工程師都對 Java 有一種近乎偏執(zhí)的喜愛,他們熱愛 Java 的簡潔與優(yōu)雅。但一旦讓他們?nèi)ミM(jìn)行 Java Script 的開發(fā),卻往往會不知所措:過度靈活的語法,無法通過編譯器進(jìn)行語法校驗(yàn),缺乏良好的調(diào)試工具等等這些,都會讓人們對 Java Script 畏手畏腳,更遑論 Ajax 的開發(fā)。
一句話, Java 社區(qū)需要 Ajax ,需要它來提升基于 JavaEE 的 Web 應(yīng)用的人機(jī)體驗(yàn);但是,人們并不喜歡 Ajax 目前的開發(fā)模式" title="開發(fā)模式">開發(fā)模式。無疑,我們需要一種新的解決方案。
誰來拯救 JavaEE 的 Ajax ?
我給出的答案是 JSF 。目前,關(guān)于 JSF 的一種流行說法是“悲劇人生: Sun 讓 JSF 光著身子降臨到 Java Web 世界”。然而,我的看法卻是:作為一種革命性的服務(wù)器端組件技術(shù), JSF 猶如早晨八九點(diǎn)鐘的太陽,前途不可限量。
讓事實(shí)說話,我們先來看看 JSF 請求 / 響應(yīng)過程的標(biāo)準(zhǔn)生命周期:
????????????圖1 :JSF 的生命周期
??? 通過上圖可以觀察到,任何一個 JSF“Faces Request” 請求,經(jīng)過 Restore View 、 Apply Request Values 、 Process Validations 、 Update Models 、 Invoke Application 等階段以后,產(chǎn)生了一個 “Render Response” 返回給客戶端" title="客戶端">客戶端。那么,常規(guī) JSF 引擎是如何實(shí)現(xiàn)上述過程的呢?
??? ??
??? 回顧一下常規(guī) JSF 引擎針對請求與響應(yīng)的過程:首先,客戶端請求某個資源,產(chǎn)生一個 Faces Request ;服務(wù)器端接收到此請求以后,經(jīng)過一系列后臺處理,產(chǎn)生一個 Faces Response 。我們注意到:響應(yīng)的 Content-Type 是 text/html ,而產(chǎn)生的內(nèi)容主體是一段 HTML 文本;瀏覽器在接收到 HTML 文本以后,進(jìn)行整個頁面的渲染與刷新。
無需寫 Ajax 代碼的 Ajax Enabled 應(yīng)用
????? 我用自己開發(fā)的 JSF 引擎,這樣處理上述過程(詳見參考資料" title="參考資料">參考資料 www.OperaMasks.org ),如下圖所示:
?
???????? 圖 3 : OperaMasks JSF 實(shí)現(xiàn)的請求與響應(yīng)過程
???? 首先可以觀察到, Faces Request 的發(fā)出是基于 “x-requested-by: XML Http Request” ,也就是說,這是一個 Ajax 請求,而該請求在到達(dá)服務(wù)器端以后,服務(wù)器端所產(chǎn)生的 Faces Response 同常規(guī) Faces Response 相比也發(fā)生了變化: Content-Type 不再是 text/html ,變成了 text/javascript ;并且,響應(yīng)的主體也不再是 html 文本,而是一堆 script 腳本。瀏覽器在接收到響應(yīng)以后,再也不需要進(jìn)行整個頁面的渲染與刷新,而只僅僅需要執(zhí)行這段腳本內(nèi)容,將頁面的控件進(jìn)行更新即可。
????? 顯而易見,通過上述 JSF 技術(shù),我們獲得了:
????? - 基于 Ajax 的請求、應(yīng)答、及頁面控件的更新
????? - 數(shù)據(jù)傳輸量明顯減少
????? - 避免整個頁面的刷新,更好的用戶體驗(yàn)
????? - 系統(tǒng)保持敏捷、高效
???? 換言之:任何標(biāo)準(zhǔn) JSF 應(yīng)用,只需將其在 OperaMasks JSF 引擎上運(yùn)行,就可以達(dá)到這樣的效果。我們并沒有寫任何一行 Ajax 的代碼,但是,我們的應(yīng)用卻是自然而然的 Ajax Enabled 的應(yīng)用。大道至簡,大象無形。
奧妙所在: JSF 的 Render 機(jī)制
為什么可以這樣?
JSF 組件只是特定狀態(tài)和行為的載體,而組件以什么形式去和用戶交互,是完全可定制的、獨(dú)立于該特定的表現(xiàn)語言,可以是 HTML 、 WML 或者其他形式;具體是什么,可以通過指定 JSF 組件的 Render Kit 來實(shí)現(xiàn),而每一種 Render Kit ,對應(yīng)于組件作者寫的同一風(fēng)格和形式的一系列 Render 。
比如,如果想在網(wǎng)頁中實(shí)現(xiàn)圖表功能( Chart) , MSIE 有 VML , Gecko 和 Opera 有 SVG ;而在服務(wù)器端只需要簡單地判斷一下瀏覽器類型,就可以選擇一個 Render Kit ,生成不同的客戶端表現(xiàn)來完成相同功能――這是用常規(guī) JSP 技術(shù)很難完成的任務(wù)。
通俗的說, JSF 組件可以翻譯成任何你想要的形式。 So , JSF 框架比現(xiàn)有其它開源框架具有更強(qiáng)的生命力。上文所述的 OperaMasks JSF ,其容器級別 Ajax 實(shí)現(xiàn),正是靈活應(yīng)用 Render Kit 的具體案例。
從容器級別對 Ajax 予以支持的 JSF 引擎
我們提出的 JSF 是直接由 JSF 容器來處理 Ajax 請求的,它會根據(jù)請求類型來判斷這是一個正常 HTTP 請求還是一個 Ajax 請求:如果是常規(guī) HTTP 請求就運(yùn)行 JSP 頁面,生成頁面文檔(特定的,對于 Ajax Render kit ,要加入一些 Ajax 基礎(chǔ) JavaScript 代碼);如果是 Ajax 請求,服務(wù)器對請求參數(shù)正常解碼,并執(zhí)行 JSF 中除頁面輸出階段以外的所有其他階段,生成一個 JSF 組件樹。
一直到這一步為止,處理方式與對普通 HTTP 請求的處理完全一致,唯一不同的是:在隨后 Render Response 階段,容器除了調(diào)用組件作者寫的 Ajax 功能 Renderer 以外,更重要的是在生成響應(yīng)頁面時,會過濾掉一切不會變化的靜態(tài)內(nèi)容――也就是說,靜態(tài)內(nèi)容不會生成到響應(yīng)頁面中去,而對每一個動態(tài)內(nèi)容則會生成一個相應(yīng) JavaScript 代碼(可以更進(jìn)一步優(yōu)化為只有變化了的動態(tài)內(nèi)容才處理)。這樣,傳給客戶的 Ajax 應(yīng)答實(shí)際上是由這樣一些 JavaScript 語句構(gòu)成。在 Ajax 響應(yīng)返回到客戶端時,就可以自動由 Ajax 回調(diào)函數(shù)執(zhí)行這些 JavaScript 語句,完成對頁面即時的、局部的更改,而不需要刷新整個頁面。依賴 JSF 組件的具體功能,甚至可以改變頁面的外觀。而整個 Ajax 機(jī)制由 JSF 引擎提供,對用戶完全透明。
實(shí)際上,在 JSF 規(guī)范中 JSF 頁面輸出階段所采用的 Render Kit 是可替換的,默認(rèn)的 HTML_BASIC Render Kit 輸出的是標(biāo)準(zhǔn) HTML 語法,不包含任何 Java Script 代碼。我們提出的 JSF 引擎實(shí)現(xiàn)了一個 Ajax Render Kit ,可以在 HTML 文檔中嵌入 Java Script 代碼來實(shí)現(xiàn) Ajax 特性,而替換 Render Kit 只需要修改配置文件即可。
簡單地說,這種 JSF 引擎為每個標(biāo)準(zhǔn)組件都實(shí)現(xiàn)了相應(yīng)的 Ajax Render , 比如對 UICommand 組件,其 Ajax Render 會在 onclick 事件中加入 JavaScript 的 Ajax 提交代碼,向服務(wù)器提交 Ajax 請求。通過這種方式,任何一個包含標(biāo)準(zhǔn) JSF 組件的 Web 應(yīng)用,都可以通過只更改 Render Kit 配置為 Ajax 來實(shí)現(xiàn) Web 應(yīng)用 Ajax 化。而對于第三方" title="第三方">第三方的組件,可能本身并不支持 Ajax ,但使用一個名為
例如, Apache myfaces 的 Tomahawk 項(xiàng)目提供了一個 Tree 組件,這個組件本身并不支持 Ajax ,每當(dāng)按下一個 Tree 結(jié)點(diǎn)都將重新刷新整個頁面。使用
綜上, JavaEE 需要 Ajax ,但并不需要傳統(tǒng)的 Ajax 開發(fā)模式。通過我們提出的 OperaMasks JSF 技術(shù),我們不再需要知道什么是 Ajax ,而我們的應(yīng)用卻是自然而然的 Ajax Enabled 應(yīng)用。
因此,我們認(rèn)為: JavaEE Without Ajax !