張帆,劉嵩
在傳統(tǒng)Web MVC架構(gòu)模式中,人們往往指的是服務(wù)器端MVC,而忽略了瀏覽器端MVC。這是人們對(duì)MVC架構(gòu)模式認(rèn)識(shí)上的局限。由于它只注重服務(wù)器端功能,使得瀏覽器端 Web表現(xiàn)層的靈活性不夠,無(wú)法實(shí)時(shí)交互數(shù)據(jù)。針對(duì)這個(gè)問(wèn)題,我們引入現(xiàn)代Web MVC架構(gòu)模式。它通過(guò)構(gòu)建瀏覽器端MVC和服務(wù)器端MVC,提高了Web交互數(shù)據(jù)的實(shí)時(shí)性,同時(shí)增強(qiáng)了瀏覽器端 Web表現(xiàn)層的異步通信能力和靈敏度。
本文通過(guò)對(duì)經(jīng)典MVC架構(gòu)模式的簡(jiǎn)要分析和歸納,闡明了MVC在軟件開(kāi)發(fā)中的重要作用。針對(duì)人們對(duì)傳統(tǒng)Web MVC模式認(rèn)識(shí)上的局限,分析討論了現(xiàn)代Web MVC架構(gòu)模式的優(yōu)勢(shì)。最后結(jié)合具體應(yīng)用,進(jìn)一步比較了Ajax、Comet等 Web架構(gòu)模式的有效性,為軟件開(kāi)發(fā)者和架構(gòu)師提供了有益的參考。
MVC英文即 Model-View-Controller,它是為編程語(yǔ)言Smalltalk-80發(fā)明的一種目前廣泛流行的軟件設(shè)計(jì)模式,主要包含三個(gè)層面:模型(Model),視圖(View),控制器(Controller)。使用MVC的目的是將創(chuàng)建和操作數(shù)據(jù)的代碼分離即模型、視圖、控制器的分離。
然而傳統(tǒng)Web MVC架構(gòu)模式面臨二個(gè)問(wèn)題:一是服務(wù)器端接收請(qǐng)求后通過(guò)控制器從模型中獲取相應(yīng)數(shù)據(jù)并生成視圖,再response到客戶端,若頁(yè)面進(jìn)行局部刷新,就不得不發(fā)送整個(gè)頁(yè)面的數(shù)據(jù),這就包含了大量冗余信息。征對(duì)這個(gè)問(wèn)題,我們引入Ajax客戶端增強(qiáng)技術(shù),這將在第三節(jié)進(jìn)行討論;二是由于服務(wù)器端主要是采用分布式結(jié)構(gòu),因此當(dāng)服務(wù)器端模型變化后,它無(wú)法立即在服務(wù)器端將變化的數(shù)據(jù)即時(shí)發(fā)送給客戶端。因而存在實(shí)時(shí)性不足,頁(yè)面內(nèi)容無(wú)法自動(dòng)更新等問(wèn)題。通過(guò)引入Comet服務(wù)器端push技術(shù)可以解決這個(gè)問(wèn)題,這將在第四節(jié)進(jìn)行討論。
客戶端與服務(wù)器端在進(jìn)行數(shù)據(jù)交互過(guò)程中,MVC架構(gòu)實(shí)際應(yīng)用在Browser-Server二端,即瀏覽器端MVC和服務(wù)器端MVC。服務(wù)器端控制器接收到用戶請(qǐng)求后,從數(shù)據(jù)模型中取出相應(yīng)數(shù)據(jù)并生成服務(wù)器端視圖,再response到客戶端。此時(shí)服務(wù)器端視圖V2實(shí)際上包括了瀏覽器端視圖V1、瀏覽器端控制器 C1、以及少量數(shù)據(jù)模型 M1,即V2={V1+C1+M1},從而構(gòu)建了瀏覽器端MVC架構(gòu),如圖1所示。
由圖1可以看出,服務(wù)器發(fā)送給瀏覽器的就不僅僅是呈現(xiàn)給客戶的視圖,而是具有業(yè)務(wù)邏輯和控制器處理功能的XML數(shù)據(jù)代碼。服務(wù)器發(fā)送 XML數(shù)據(jù)后,首先由瀏覽器端控制器和數(shù)據(jù)模型獲取并由控制器進(jìn)行相應(yīng)處理,最后生成瀏覽器端視圖呈現(xiàn)給用戶。當(dāng)用戶發(fā)送請(qǐng)求時(shí),可將請(qǐng)求交給瀏覽器端控制器處理,由瀏覽器端控制器與服務(wù)器進(jìn)行數(shù)據(jù)交互。
通過(guò)使用 Ajax客戶端增強(qiáng)技術(shù),構(gòu)建瀏覽器端 MVC架構(gòu)模式,來(lái)彌補(bǔ)Web客戶端交互能力不足的問(wèn)題。
Ajax全稱(chēng)為“Asynchronous JavaScript and XML”,是指一種創(chuàng)建交互式網(wǎng)頁(yè)應(yīng)用的網(wǎng)頁(yè)開(kāi)發(fā)技術(shù)。具體包括:基于XHTML 和CSS標(biāo)準(zhǔn)的表示、使用 Document Object Model進(jìn)行動(dòng)態(tài)顯示和交互、使用XML HttpRequest與服務(wù)器進(jìn)行異步通信、使用JavaScript進(jìn)行綁定。其中Ajax 最主要的特征就是XML HTTPRequest 對(duì)象的使用和DOM 的處理。
通過(guò)引入Ajax技術(shù),構(gòu)建了瀏覽器端MVC架構(gòu)。主要表現(xiàn)在:通過(guò)使用XML HttpRequest,可以在瀏覽器端通過(guò)發(fā)送HTTP請(qǐng)求與后臺(tái)服務(wù)器進(jìn)行動(dòng)態(tài)異步數(shù)據(jù)交互。當(dāng)用戶在當(dāng)前頁(yè)面發(fā)送一個(gè)請(qǐng)求后,它可以通過(guò)Ajax的XML HttpRequest向服務(wù)器端控制器進(jìn)行異步請(qǐng)求,然后控制器從數(shù)據(jù)模型中獲取相關(guān)數(shù)據(jù)并生成服務(wù)器端視圖,并response到瀏覽器端。瀏覽器端Ajax獲取服務(wù)器端的XML文件后,將其解析并存儲(chǔ)在文檔對(duì)象模型(DOM)中,最后生成當(dāng)面頁(yè)面呈現(xiàn)給用戶。這樣用戶再進(jìn)行一些數(shù)據(jù)處理時(shí),可以通過(guò)Ajax技術(shù)直接從Ajax的文檔數(shù)據(jù)模型(DOM)中獲取數(shù)據(jù),而不必再發(fā)送一個(gè)請(qǐng)求到服務(wù)器端。只有確定需要從服務(wù)器讀取新數(shù)據(jù)時(shí)才由Ajax引擎代為向服務(wù)器提交請(qǐng)求。這樣通過(guò)引用Ajax技術(shù)便在瀏覽器端實(shí)現(xiàn)了控制器,數(shù)據(jù)模型以及視圖的功能。這便是瀏覽器端MVC架構(gòu)模式。
瀏覽器端控制器組件可以通過(guò) Ajax的 XML HttpRequest技術(shù)來(lái)異步發(fā)送請(qǐng)求,使得瀏覽器與服務(wù)器的數(shù)據(jù)交互可以異步交互傳輸。這樣可以不用刷新整個(gè)頁(yè)面就能與服務(wù)器端進(jìn)行數(shù)據(jù)交互,使得客戶端看起來(lái)像即時(shí)響應(yīng)的桌面程序那樣,加快了瀏覽器的響應(yīng)速度,節(jié)省了用戶等待時(shí)間。圖2為基于Ajax技術(shù)的Web交互過(guò)程。
由圖2可以看出,瀏覽器呈現(xiàn)給用戶的是連續(xù)響應(yīng)的,基于Ajax應(yīng)用程序的數(shù)據(jù)的顯示和傳輸是異步進(jìn)行的。當(dāng)數(shù)據(jù)請(qǐng)求或數(shù)據(jù)傳輸正在進(jìn)行時(shí),原來(lái)的數(shù)據(jù)顯示界面可以不受影響。即Ajax程序可以僅向服務(wù)器端發(fā)送并取回必需的數(shù)據(jù),同時(shí)很多處理工作可以在瀏覽器端完成。因此瀏覽器端MVC架構(gòu)模式可以在很大程度上提高Web表現(xiàn)層的交互能力。
為了提高 Web交互數(shù)據(jù)的實(shí)時(shí)性,本節(jié)介紹了 Comet技術(shù),來(lái)對(duì)服務(wù)器端MVC架構(gòu)模式進(jìn)行改進(jìn),增強(qiáng)服務(wù)器端的MVC數(shù)據(jù)處理能力。
盡管通過(guò)引入Ajax技術(shù),用戶可以動(dòng)態(tài)異步地向服務(wù)器發(fā)出請(qǐng)求。但這種請(qǐng)求無(wú)法保證客戶端獲取的數(shù)據(jù)是最新的。因?yàn)閿?shù)據(jù)模型可能在服務(wù)器端發(fā)出信息后就進(jìn)行了更新,因此無(wú)法進(jìn)行實(shí)時(shí)通信。
為了解決Ajax實(shí)時(shí)性不足的問(wèn)題,我們可以使用二種方法:第一種是瀏覽器每隔一段時(shí)間向服務(wù)器發(fā)出輪詢以進(jìn)行更新,即輪詢方法;第二種方法是服務(wù)器始終打開(kāi)與瀏覽器的連接并在數(shù)據(jù)更新時(shí)立即發(fā)送給瀏覽器的長(zhǎng)連接技術(shù),即Comet技術(shù)。
輪詢方法的主要缺陷: 為使客戶端瀏覽器刷新當(dāng)前頁(yè)面,多長(zhǎng)時(shí)間去服務(wù)器查詢成了問(wèn)題。高頻率輪詢會(huì)使網(wǎng)絡(luò)承載過(guò)重,影響服務(wù)器速率;低頻率輪詢又會(huì)錯(cuò)過(guò)更新或傳送一些失去時(shí)效的信息。因此使用Comet技術(shù)則優(yōu)勢(shì)明顯,它不會(huì)產(chǎn)生大量通信量。同時(shí)在數(shù)據(jù)發(fā)生改變時(shí),可將即時(shí)數(shù)據(jù)實(shí)時(shí)地“推送”給客戶端。下文將詳細(xì)介紹 Comet技術(shù)。
Comet就是一種服務(wù)器端 push技術(shù),就是當(dāng)客戶端向服務(wù)器發(fā)送一個(gè)請(qǐng)求后,服務(wù)器接受它,并使用一個(gè)無(wú)限循環(huán)將客戶端所需的數(shù)據(jù)push到response中,只要response不關(guān)閉,服務(wù)器就會(huì)將更新的數(shù)據(jù)推送給客戶端。它通過(guò)保持一個(gè)長(zhǎng)期即時(shí)更新的連接,持續(xù)從服務(wù)器端獲取新的信息,由此實(shí)現(xiàn)實(shí)時(shí)通信。
Comet來(lái)源于Publish/Subscribe 設(shè)計(jì)模式,使得服務(wù)器端數(shù)據(jù)與客戶端數(shù)據(jù)時(shí)刻保持一致。若數(shù)據(jù)發(fā)生更新,則服務(wù)器端必須將這些更改后的數(shù)據(jù)傳送出去以達(dá)到對(duì)象間的同步。
通過(guò)引入Comet,使得客戶端必須在異步初始化到服務(wù)器端的連接時(shí)保持工作。在服務(wù)器端,即使不能馬上對(duì)請(qǐng)求做出回應(yīng),連接也要保持直到服務(wù)器端相關(guān)數(shù)據(jù)發(fā)生改變。當(dāng)數(shù)據(jù)模型發(fā)生變化時(shí),服務(wù)器端通過(guò)之前已經(jīng)建立好的連接把產(chǎn)生變化的數(shù)據(jù)推送到客戶端。如果存在并發(fā)的多個(gè)事件,服務(wù)器便可在此連接上發(fā)送多個(gè)事件數(shù)據(jù)而無(wú)需客戶端每次都明確發(fā)出請(qǐng)求,Comet工作模式如圖3。
圖3顯示的Comet應(yīng)用程序異步響應(yīng)模式圖。從圖中我們可以看出,服務(wù)器端可以在任意時(shí)刻向客戶端發(fā)送數(shù)據(jù),而不需要等待客戶的請(qǐng)求。數(shù)據(jù)在一個(gè)預(yù)先打開(kāi)的管道上傳送,這種方法可以大幅度減少數(shù)據(jù)傳輸?shù)难舆t。若數(shù)據(jù)有所更新,服務(wù)器便可即時(shí)將數(shù)據(jù)推送到客戶端。因此Comet的引入,增強(qiáng)了服務(wù)器處理實(shí)時(shí)數(shù)據(jù)的能力。
學(xué)生宿舍管理系統(tǒng)以MyEclipse6.0作為開(kāi)發(fā)平臺(tái),數(shù)據(jù)庫(kù)用的是Oracle9i,使用的編程語(yǔ)言有Java,Jsp,JavaScript,DWR2.0,Ext JS等。
本系統(tǒng)通過(guò)在客戶端引入Ajax技術(shù),構(gòu)建了瀏覽器端MVC架構(gòu)。在客戶端與服務(wù)器之間創(chuàng)建了Ext JS腳本文件,使得宿舍管理員向服務(wù)器發(fā)出請(qǐng)求時(shí),由Ext JS腳本文件單獨(dú)與后臺(tái)服務(wù)器建立連接,實(shí)現(xiàn)了動(dòng)態(tài)異步數(shù)據(jù)交互。如圖4所示,若進(jìn)行樓棟,舍區(qū),收費(fèi)標(biāo)準(zhǔn),性別等信息進(jìn)行設(shè)置時(shí),管理員不需要向服務(wù)器發(fā)出請(qǐng)求,而是直接從瀏覽器端 Model獲取信息。當(dāng)管理員需要再次讀取曾經(jīng)讀取過(guò)的信息,則可直接從瀏覽器端Ajax文檔數(shù)據(jù)模型(DOM)中獲取,而不必再次與服務(wù)器進(jìn)行交互。只有當(dāng)宿舍管理員需要獲取新的數(shù)據(jù)時(shí),才由Ajax引擎與服務(wù)器進(jìn)行數(shù)據(jù)交互處理。
圖4 房間信息管理
通過(guò)使用jetty構(gòu)建Comet服務(wù)器對(duì)系統(tǒng)進(jìn)行改進(jìn),使得宿舍管理員在進(jìn)行數(shù)據(jù)操作時(shí)獲取的數(shù)據(jù)更具有實(shí)時(shí)性。由于采用分布式結(jié)構(gòu),當(dāng)多個(gè)宿舍管理員同時(shí)操作本系統(tǒng)時(shí),往往他們會(huì)對(duì)同一對(duì)象進(jìn)行操作。顯示效果如圖5,從圖中可以看到當(dāng)某一樓棟的某一房間的待住人數(shù)為1時(shí),其中一個(gè)管理員對(duì)其進(jìn)行了添加使得服務(wù)器端此房間待住人數(shù)變?yōu)?。這意味著其他管理員的當(dāng)前操作頁(yè)面也必須實(shí)時(shí)地更新此信息,才能確保數(shù)據(jù)的準(zhǔn)確。在 Comet架構(gòu)模式應(yīng)用中,一旦服務(wù)器發(fā)現(xiàn)有數(shù)據(jù)更新,它就主動(dòng)把最新的數(shù)據(jù)以“推送”的方式發(fā)送到客戶端,使得宿舍管理員獲取的數(shù)據(jù)更及時(shí),更具有實(shí)時(shí)性。同時(shí)也避免了宿舍管理員為了獲取實(shí)時(shí)信息,而多次刷新當(dāng)前頁(yè)面。
圖5 添加學(xué)生入住信息界面
利用 Ajax技術(shù)在表現(xiàn)層的優(yōu)勢(shì),構(gòu)建瀏覽器端 MVC架構(gòu),增強(qiáng)了客戶端動(dòng)態(tài)交互能力。同時(shí)應(yīng)用 Comet架構(gòu)模式構(gòu)建后臺(tái)服務(wù)器,實(shí)現(xiàn)了實(shí)時(shí)通信。在學(xué)生宿舍管理系統(tǒng)中,通過(guò)使用Ajax和Comet技術(shù),使得系統(tǒng)在功能上都得到明顯改進(jìn)和提高。
[1]陳鄭偉,彭巖,莊力可.基于 Ajax 的電子政務(wù)平臺(tái)的研究與應(yīng)用[J].計(jì)算機(jī)工程與應(yīng)用,2007 ,43 (5):1962199.
[2]Wilkins Greg.Ajax ,Comet and J etty.[2006211202].[EB/OL].http://www.webtide.com/downloads/whitePaperAjaxJetty.html,2006.
[3]周牧,談曉軍,左 翔,崔雨勇.基于AJAX和XML 的WebGIS 系統(tǒng)研究.計(jì)算機(jī)工程,2009,7.
[4]Garret J J.AJAX: New Approach to Web Applications[J/OL].(2005-02-18).http://www.adaptivepath.com/publications/essays/archives/000385.
[5]王默玉,劉巖,劉林,李成榕,王輝.Web2.0-Comet-Continuations 模式在局部放電實(shí)時(shí)監(jiān)測(cè)中的應(yīng)用[J].吉林大學(xué)學(xué)報(bào)(工學(xué)版)2009,1 第39卷第1期.
[6]劉鑫,陳偉.基于AJAX和Server Push的Web樹(shù)組件設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與設(shè)計(jì),2009,30(3).