現在,更高級別的JSF和AJAX整合方式到來了。確切的說,這種更加容易使用的解決方案就是在使用JSF基礎上再加上AJAX擴展。我上面已經提到了,現在有很多的解決方案了,今天我要談論的是其中之一的Project Dynamic Faces。當你在使用這些解決方案時,通常是不需要去了解任何JavaScript知識的,因為它已經為你封裝好Javascript的編程實現,你只需要正常使用JSF的API去編程,就能達到AJax的效果。當然,你如果需要的話,Dynamic Faces也是允許你去手工編寫Javascript的,(通過自己編寫的JavaScript)你可以實現更強大復雜的操作。據我所之Dynamic Faces是目前為止唯一一個可以正確處理JSF上下文敏感(context sensitive)的AJAX交互組件,原因是它充分利用了JSF1.2的優勢(注:雖然專家組們在討論JSF2.0規范,但現在實際使用的JSF最新版本是1.2)。現在我們來看一個demo,假設說你有一個數據列表,當你隨便碰到某個單元格時(注:類似於操作Excel.當我們在使用Excel的時候,光標所移動到的任何單元則都是可以隨便操作,並保存的),你想通過AJax去處理你所指定的那個單元格時,所有的單元格的在頁面渲染完後狀態都是可隨時存儲的,便於隨時修改,此時顯示在頁面的data table(數據表格)就是dataset所持有的數據呈現給外部的一個窗口;當你在修改完data table的某行記錄或某行記錄中的某列後,想postback一下(注:postback指的是用戶返回到以前訪問過的一個頁面,與頁面對應的視圖已經存在,所以只需恢復它。在這種情況下,JSF 使用現有視圖的狀態信息重新構造它的狀態。)這時你需要將data table設置成自身,從而可以感知到改動的數據.JSF1.2已經添加了一些新特性來支持這樣的應用場合.這還得多虧我們的專家組成員Jacob Hookom,同時他也是Facelets的作者.(注:Facelets是用來建立JSF應用程序時的一個可供選擇的表現層技術)
我之所以為Dynamic Faces亮起紅燈(表示警告),是因為JSF1.2有這個特性,它才能實現這個功能,而且還不是很成熟。雖然它現在當已經加入到Sun Web Developer Pack中去了,不過仍然處於0.1版本,與其它你可能聽說過的AJax解決方案相比,缺乏大量的測試。
下一級別的的JSF和AJAX整合方案就是直接使用帶AJAX的JSF組件。用這類組件,與使用普通的JSF組件沒有什麼兩樣,實際上它們已經將AJAX所做的事都全部為你封裝好了。這些組件也許會通過phase listener,filter或者其它什麼配置來處理AJax請求,但不需要你親自去處理。現在已經有一些不錯的組件可以使用了,而且相當一部分還支持JSF1.1。這些組件中,有些是開源的,有些要付費的,總之這是一個相當大的市場,你可以登錄www.jsfcentral.com,這是由另一名專家組成員Kito Mann運作的,裡面有很多非常優秀的組件,並且你還可以從中了解目前JSF組件的市場行情。
退一步說,如果在眾多JSF組件中,仍然沒有讓你感到滿意的話,你就得親自寫代碼了,要不然用DynaFacesr擴展也是可以的。
好了,到這裡,當我在考慮JSF整合AJAX這部分的時候,一個大難題浮現在我腦中:是應該支持各種途徑去使用AJax(比如說允許自己編寫客戶端代碼)呢,還是像通常的web應用程序那樣,只采用UI標簽方式呢?我的觀點是,不支持,沒有必要。關於這個點會在小組討論中談到。如果采用Dojo方式的話,你的大量VIEwLogic(頁面邏輯)綁定在客戶端上,這樣做也許只是將服務器變得負擔輕一些;而使用GWT的話,你得將Java編譯成Javascript代碼,但此時的JavaScript仍然運行在客戶端,然後使用一個類似於RMI的機制通過服務器端來來回回不停的調用。但以上這些只是考慮了客戶端這個方面!另一方面,你仍然可以使用基於服務端開發工具,去開發你的組件,然後markup(標記)在服務端上,這樣就可以通過服務端呈現給客戶端,這一類的解決方案的思想就是將UI組件的狀態保存在服務端.我也覺得無論從成熟度,相應工具的支持程度還是可維護性上來說,這樣做都有很大的優勢.按照我的話來說,將大量的UI組件邏輯保存在服務器上,你會發現更加易去維護.
因此,對於上述問題的一種解決辦法是,把JSF當作web應用程序開發的基礎,並且你只需要在此基礎上略施小計就可以得到AJAX支持.JSF的AJAX擴展就是這麼實現的,我現在將一些熟悉的擴展列出來:Dynamic Faces,ICEfaces,AJax for JSF(現在和JBoss搭上了伙,成為了RichFaces),BackBase還JackBe..總之,在www.JSfmatrix.Net站點可以看到這些解決方案之間的比較.另一個不錯的解決辦法來自於JCP,我們會將現在上面列出的那些擴展中先進的思想提交給JSF專家組,並且我們正准做出更多的努力,但現在無法透露太多。(看來JCP的專家組們還是沒有改變辦事過於拖拉的毛病,因此估計官方的JSF和AJax方案一時半會是出不來了。)
那麼為什麼從設計的角度就要將JSF和AJAX整合在一起呢?因為JSF天生有著Swing的特性,如果你喜歡采用基於組件的面向對象方式進行編程,你會發現JSF的設計就是為AJAX而准備的.一些JSF的特性使得AJax變得更加友好並進一步擴展了JSF UI組件模型;一個建立在servlet之上,定義良好的請求處理生存周期(request processing life cycle)管理著WebRequest各種狀態(phase)下不同的生存周期,比起單純的request, response要豐富的多,甚至我感覺這一點在脫離JSF仍然十分有用.那就是我們打算讓JSF2.0應用程序以更加偏重於clIEnt-centric方式,來貫穿整個JSF生存周期,甚至到時候要不要JSF組件都說不定了,但驗證和類型轉換等這類東西還是需要的.
另一個特性就是靈活和可擴展的組件呈現模型(Rendering Model).Rendering的概念源於組件,你可以用render kits(套件)去豐富基於Javascript的應用程序,與Html4.01相比,它的內容更加豐富。各種各樣的render kits為你隱藏了復雜的底層細節,幫助你實現網站的多種版本。這裡還有一個關於封裝的概念:JavaScript的封裝不應該交給頁面的編寫人員,應該交給組件開發人員,最終所有的JSF組件統一管理在一起,更加方便透明的保持客戶端與服務器之間的同步。
現在我們來看一些典型的AJax問題與解答:
1.跨浏覽器問題,通過封裝好的JavaScript框架已經很可做到這一點了
2.本地化和國際化問題,用JSF就可以搞定了,AJax根本不需要參與
3.Shell remoting的機制就是專門用來管理腳本,它用一種安全的方式為你的組件提供存放在class path外面的JavaScript腳本.
4.如果你覺得你寫了太多的XMLHttpRequest來來回回與服務器進行交互的話,你可以使用Dynamic Faces的批處理事件(或找一個具備批處理事件的類似替換物),一次性將所有的事件發送完成.
5.使用XML作為(AJax與服務器交互後的返回的)傳輸數據的話,要求對於某些HTML元素做一些額外的優化工作.比如說, 是Html的一個實體,但它在XML中卻什麼都不是.當XMLHttpRequest的responseXML包含 的話,Mozilla浏覽器將無法正常解析XML,它會認為這是一個無效的實體,因此,我不知道你們是不是也覺得這算是Mozilla的一個Bug呢?此時你必要按照某種方式去定義那些東西,並且確保這類問題通過JSF和AJax的方案來解決.
為現有的或即將立項的JSF應用程序插上AJAX翅膀,我個人覺得對於應用程序來說非常棒.我想我們應該可以做到讓一個已經完成的項目AJAX化(AJAXify),並且如果是新的項目的話,保證還能從中得到更多的好處.這一切還得再次得歸功Jacob Hookom天才的理念。我覺得他的Project Dynamic Faces為開發人員朝著AJax方向前進了一小步.真的!!!就兩個JSP Tag和兩個JavaScript Function需要你掌握,但就是這小小的一步,你也已經可以從中得到很多AJax特性了.
因此,這裡有一個基本的概念.將JSF的生存周期通過AJAX暴露給浏覽器,並且你想通過AJAX來操作整個View或其中的某個部分,從而達到更新一塊單獨的VIEw區域或某個組件的目的,或者干脆越過AJAX來刷新整個頁面也能實現。有時候,你希望通過使用AJax可以越過JSF的生存周期,來取得一些控制級別並且你還可以讓服務器(在不刷新頁面的情況下)來改變當前頁面的外觀或行為.通常這對於Swing或其它native UI Tookit開人員來說,很好理解:當前窗體的部分外觀或行為被更新過了,服務器當然只會去對那部分作一下修改,犯不著整個窗體都重新更新一遍。現在將這個觀念帶回到web開發中來,頁面的部分內容或行為改變了,你重繪(repaint)一下不就得了。