在網絡需求越來越多的時代,傳統的Web1.0技術由于其同步交互方式,帶來了很大網絡流量以及很差的用戶體驗,以Wiki,google Map等為代表的Web2.0技術以及RIA的應用極大地提高了網絡性能和用戶體驗,成為了Web應用領域的主力軍。在實現高用戶體驗及時交互方面,有5種技術可供選擇:1)Flex和OpenLaszlo;2)IBM?WorkplaceTMManaged Client和IBM Lotus?Expeditor;3)Faces Client Com-ponents;4)Ajax;5)HTML[1],考慮到開發難度以及具體C2C交易平臺后臺系統的特點,選擇Ajax技術。Ajax綜合了以前DHTML技術,通過XMLRequest出色地完成了異步交互功能,帶來了系統性能的很大提升。然而純Ajax代碼相當復雜,開發和調試都比較麻煩,同時需要前端美工和后臺程序員很好的合作,才能構建出好的Ajax應用。幸運的是,ExtJS提供了很好的解決方案,程序員不需要精通DHTML就可以輕易地構建一套高用戶體驗界面,同時ExtJS是基于JavaScript的,對Ajax有很好的支持。因而,后臺程序員就能脫離前臺美工來獨立構建高用戶體驗的Web系統。
1Ajax技術與ExtJS框架概述1.1Ajax原理
作為DHTML技術的升級,Ajax大部分沿用了以前的老技術,它是將一部分業務邏輯轉移到客戶端,使得客戶端不僅僅是個頁面,而且有強大的業務邏輯支撐著,一般是用JavaScript實現的,html與css負責界面的實現。從這方面講也類似于C/S結構,不過Ajax是盡可能的實現C/S結構高交互能力效果的同時又保持B/S結構的平臺無關性。
瀏覽器在執行任務時會自動裝載Ajax引擎[2]。具體過程:瀏覽器發送請求到服務器,服務器響應請求,把頁面數據(包括html,js,css文件)發送到瀏覽器,瀏覽器解析成網頁,可以將其看作是一個小型的客戶端程序,用戶可以像使用桌面應用程序一樣來操作頁面。當用戶點擊頁面上某一按鈕或其他,瀏覽器端便會相應產生一個事件,瀏覽器端控制器感應該事件,而調用相應的Model來實現相應的業務邏輯。Model利用XMLHTTPReader發送請求到服務器,服務器響應請求,回復相應的數據到瀏覽器端,然后XMLHttpReader回調callback(),接收并解析數據。一般回復的數據為txt,json或xml。最后Model利用DOM(Document Object Model,文檔對象模型)找到或創建頁面上相應的元素,將解析后的數據加載到相應的元素上,View將數據顯示在頁面,圖1是Ajax的調用示意圖。

圖1 Ajax調用示意圖Fig.1Schematic diagram of calling Ajax
基于Ajax的客戶端其實也是一個類似于服務器端的MVC實現。與傳統Web1.0技術相比,可以看出Ajax摒棄了整個頁面刷新式的交互,而是采用異步事件處理的方式來請求服務器端的關鍵數據(即不帶html標記的數據),擁有自身的業務邏輯,從而大大減輕網絡壓力和服務器的壓力。
ExtJS發源于YUI,最先由Jack Slocum開發,是采用OOP設計思想建立類庫與后臺語言無關的JavaScript框架[3],它將OOP發揮到了極致。然而ExtJS不僅僅是個JavaScript框架,它可以獨立于其他JavaScript框架通過Adapter(適配器)[4]。對于后臺程序員而言,不需要很深的網頁開發功底,就可以很快地開發出用戶體驗很高的類似桌面應用的界面,一方面減少了與美工的交流,自己來開發客戶端界面,另一方面開發出來的界面交互能力很強,能夠很好地與后端服務器結合。
ExtJS提供了Ext.ViewPort視圖類,它可以根據layout配置,實現不同的布局風格。在開發三農商城后臺管理系統時,主界面采取border(邊界)布局方式,整體布局見圖2。它根據Ext.layout.BorderLayout.Region類定義的東西南北中5個區域來布局每一個區域,每個區域為一個panel面板類的實例。同時ViewPort會自動充斥整個瀏覽器。Ext提供了Ext.onReady(fn)方法,在頁面裝載完畢后,自動運行。與Window.onLoad()不同的是,Ext.onReady(fn)是在頁面裝載完畢后,而不是等到所有的圖片和flash等裝載完畢后執行,這樣相對于傳統的Window.onLoad(),有更高的響應速度。

圖2 整體布局效果圖Fig.2The overall layout diagram
代碼如下:
Ext.onReady(function(){var mainViewPort=new Ext.ViewPort({renderTo:Ext.getBody(),layout:“border”,items:[{xtype:"panel",title:"頂部標題欄",region:"north"},{/*略*/},{/*略*/},{/*略*/},{/*略*/},{/*略*/}]})
});
Ext提供了對樹的支持,包括TreePanel樹面板,TreeNode樹節點,TreeLoader樹加載器。利用樹,可以很好的表示數據的層次結構。如創建動態類別樹結構。通過TreePanel創建一個面板,每一個類別即是一個節點,用TreeLoader異步請求服務器,得到數據,然后解析顯示到頁面上。一般數據傳輸的格式有xml和Json兩種,由于Json的數據量比較小,而且是JavaScript固有的對象支持格式,大多都使用Json的方式。下面以基于J2EE的三農商城開發中省市縣動態樹為例介紹動態樹的實現技術,圖3是省市縣動態樹效果圖。

圖3 Tree效果圖Fig.3Tree diagram
基于J2EE的省市縣動態樹客戶端開發代碼如下:Ext.onReady(function(){
var loader=new Ext.tree.TreeLoader({url:"manage/categoryMng!getTree"http://請求的地址});
//在節點內容加載前執行
loader.on("beforeload",function(loader,node){loader.baseParams.id=node.id;//向服務器端傳遞參數});
var areaTreePanel=new Ext.tree.TreePanel({id:"all",title:"類別",renderTo:Ext.getBody(),root:"all",loader:loader});
});
在服務器端,采用Struts2.1表示層框架,為了使其能方便地支持Json,使用json-plugin插件。服務器端Action代碼如下:
public class CategoryMng extends ActionSupport
{@Resource CategoryService categoryServiceBean;
private List<Node>nodes=new ArrayList<Node>();
public String getTree()throws Exception
{String id=ServletActionContext.getRequest().getParameter("id");
Set<Category>categorys=categoryServiceBean.get(id).getChildren();
//通過DAO獲取子類別
nodes=categoryServiceBean.toNodes(categorys);//轉化為節點類
return super.SUCCESS;
}
public List<Node>getNodes()
{return nodes;}
}
節點類代碼如下:
public class Node
{public String id;//序號
public String url;//鏈接地址
public boolean leaf;//是否是葉子節點
/*set和get方法略*/
}
struts.xml文件配置如下:
<packagename="manage"namespace="/manage"extends="json-default">
<action name="categoryMng"class="com.hncu.web.action.CategoryMng">
<result type="json">
<param name="root">nodes</param>
</result>
</action>
</package>
在傳統的DHTML技術中,網頁動態加載一般都是通過iframe嵌套加入網頁中,這樣每次加載都要重新引入js和css文件,嚴重情況下,一個頁面層層迭代嵌入了6、7個iframe,極大地增加了網絡壓力和客戶端CPU開銷。ExtJS提供了panel動態加載網頁的功能,可以在不重新加載js和css文件的情況下,將html嵌入指定的div中。在ExtJS3.2中,改進了動態內嵌入網頁的功能,增加了對JavaScript代碼的支持,將JavaScript作為腳本解釋型語言的特性發揮到極致。
Ext.Window動態加載實現代碼如下:
var win=Ext.Window({/*略*/})
win.load({url:"manage/productList.action",//請求的地址
params:{//帶入參數
categoryId:1,pageSize:10
},script:true
});
在B/S結構中,瀏覽器與服務器之間的交互方式是單方面的,即瀏覽器主動請求服務器,然后服務器與瀏覽器之間建立TCP/IP連接,并且兩者之間的會話是無狀態的。盡管真正意義上的雙向交互是不可能的,但是可以利用Ajax技術讓瀏覽器定時自動向服務器發出請求,達到實時更新的效果。下面以三農商城系統消息實時提醒為例來討論實時更新的實現。
客戶端代碼如下:
var htmlContent;
function ajaxInterval()
{Ext.Ajax.request({url:"updateAction",//請求的地址
method:'GET',success:function(response)
{//利用JSON進行編碼,返回JavaScript的原生類類型
var obj=Ext.util.JSON.decode(response.responseText);
for(var i=0;i<obj.length();i++)
{/*把obj組裝成html代碼賦值給htmlContent*/}
}
});
}//設置定時器
window.setInterval("ajaxRequest()",3000);
/**將htmlContent按照表現邏輯顯示到頁面上**/
系統通過window.setInterval()函數來定時執行ajaxRequest()方法,從而動態請求服務器,然后將返回的數據用JSON進行解析后,顯示到頁面,從而達到實時更新消息的效果。服務器端代碼JSON組裝代碼參考2.2。
為了避免用戶在數據輸入時遇到斷電、網絡中斷等意外時造成數據丟失,減低工作效率等問題,因而需要采用自動保存機制。自動保存機制主要有兩種方法,一種是及時保存到服務器,另一種是把數據及時保存到本地機器。第一種是定時把數據發送到服務器,讓服務器持久化到數據庫中,顯然這種方式代價很大,增加了Web服務器和數據庫服務器的壓力;第二種是先保存到本地機器cookie中,待故障恢復后自動發送到服務器持久化。
TextArea狀態保存代碼實現如下[5]:
StatefulTextArea=Ext.extend(Ext.form.TextArea,{stateEvents:['change'],//設置狀態監聽事件
getState:function(){return{text:this.value//設置保存的數據為TextArea的值}},
applyState:function(state){this.setValue(state.text);//設置狀態應用事件}
});
//設置狀態管理器提供者為Cookie
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
expires:new Date(new Date().getTime()+(1000*60*60*24*30))//保存一個月}));
在ExtJS3.2中,單extjs-all.js文件就有600多K,按1Mb/s的網速算,單加載這個文件就要耗費大約5 s,使得響應時間增加了很多。其實ExtJS中的js文件是可以定制的,可以根據自己的需要來導入關聯的js文件,而沒必要一次性導入所有的庫。另一方面,即使要用到某個js文件,如果不是馬上要用到的話,也沒必要一開始就加載進去,可以采用延遲加載的原則,用到時再加載。
造成瀏覽器與服務器之間傳輸量大的很大一部分原因是由于傳輸數據中存在大量的空格等無用字符,因此,采用GZIP做為http壓縮工具,對靜態文件html,javaScript,css,Text以及動態JSP,Servlet輸出的網頁進行壓縮,從而減少網絡流量。tomcat容器下GZIP壓縮配置參考文獻[6]。
緩存技術已經應用到計算機領域的各個方面,在J2EE方面,數據庫,業務邏輯層,表現層都可以設置緩存。它通過對大量訪問同一種資源進行保存,而減少不必要的服務器負載壓力,達到提高效率的目的。頁面緩存是通過html提供的meta標簽的http-equiv屬性來實現。包括:
1)<meta http-equiv="Expires"content="">可以用于設定網頁到期時間,一旦過期則必須到服務器上重新調用,必須使用GMT時間格式;
2)<meta http-equiv="Pragma"content="no-cache|nostore|max-age|max-state|min-fresh|onif-cached">是用于設定禁止瀏覽器從本地機緩存中調閱頁面內容,設定后一旦離開網頁就無法從Cache中再調出;
3)<meta http-equiv="cache-contro"content="no-cache|no-store|max-age|max-state|min-fresh|onif-cached">指定和響應遵循的緩存機制,它不會影響另一個消息處理的緩存過程。
在頁面緩存方面,OSCache給我們提供了一個良好的框架,通過這個工具,可以自由的選擇緩存區域(硬盤,內存),緩存范圍(頁面級緩存和部分頁面內容緩存)。同時也提供了豐富的標簽,方便了JSP的配置。詳細配置參考文獻[7]。
Ajax作為Web2.0的核心技術之一,帶來了Web用戶體驗革命性的改變。ExtJS作為Ajax的客戶端UI框架,很大程度上減少了系統開發成本,同時又保證了系統的美化以及頁面響應速度。利用Ajax+ExtJS組合,有效避開了傳統B/S結構用戶體驗差的特點,又具有了C/S結構的強交互能力,同時還具有很好的可移植性和可維護性。作為RIA應用的新生兒,ExtJS將走得更遠。
[1]宋轉玲,劉海行,代亮,等.基于ExtJS開發的海洋科學數據共享平臺[J].海洋科學,2010,34(2):4-9.SONG Zhuan-ling,LIU Hai-xing,DAI Liang,et al.Qingdao oceanic data service system based on ExtJS[J].Marine Sciences,2010,34(2):4-9.
[2]鄭玲,蒲強,劉曉建.基于AJAX技術構建汽輪機組遠程故障監測系統的設計與研究[J].中國電力教育,2008,(S2):353-355.ZHENG Ling,PU Qiang,LIU Xiao-jian.Design and research of the turbine remote fault monitoring system based on AJAX[J].China Electric Power Educationm,2008,(S2):353-355.[3]雷鐳,陳俊.基于ExtJS及Pushlet實現Web及時交流[J].軟件導刊,2010,9(2):118-120.LEI Lei,CHEN Jun.Implementation of Web communication by ExtJS and pushlet[J].Software Guide,2010,9(2):118-120.
[4]Frederick S,Ramsay C,Steve Cutter Blades.Learning ExtJS[M].Packt Publishing Ltd.,2008:10-21.
[5]ExtJS3.2 document[EB/OL].(2010-4-12)[2010-10-1].http://dev.sencha.com/deploy/dev/docs/.
[6]Apache Tomcat6.0 document[EB/OL].(2010-3-24)[2010-10-1].http://fangrn.javaeye.com/blog/623339.
[7]Opensymphony[EB/OL].(2009-3-6)[2011-3-1].http://www.opensymphony.com/oscache/wiki/CacheFilter.html.