知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
您當(dāng)前位置>首頁 » 新聞資訊 » 網(wǎng)站建設(shè) >
反向Ajax,第5部分:事件驅(qū)動(dòng)的Web開發(fā) (轉(zhuǎn))
發(fā)表時(shí)間:2012-7-2
發(fā)布人:葵宇科技
瀏覽次數(shù):48
這一文章系列探討了如何使用反向Ajax(Reverse Ajax)技術(shù)開發(fā)事件驅(qū)動(dòng)的web應(yīng)用,第1部分內(nèi)容介紹了實(shí)現(xiàn)反向Ajax通信的不同方式;第2部分內(nèi)容說明了如何使用WebSocket來實(shí)現(xiàn)反向Ajax,并討論了使用Comet和WebSocket的web服務(wù)器的局限性;第3部分內(nèi)容探討了實(shí)現(xiàn)自己的Comet或是WebSocket通信系統(tǒng)的難點(diǎn),并介紹了Socket.IO;第四部分內(nèi)容談到了Atmosphere和CometD。在本系列的最后一部分內(nèi)容中,我們來了解事件驅(qū)動(dòng)的開發(fā),使用附帶的源代碼來構(gòu)建一個(gè)示例性的事件驅(qū)動(dòng)web應(yīng)用
前言
這一文章系列展示了如何使用反向Ajax(Reverse Ajax)技術(shù)開發(fā)事件驅(qū)動(dòng)的web應(yīng)用,第1部分內(nèi)容介紹了反向Ajax、輪詢(polling)、流(streaming)、Comet和長輪詢(long polling);第2部分內(nèi)容說明了如何使用WebSocket來實(shí)現(xiàn)反向Ajax,并討論了使用Comet和WebSocket的web服務(wù)器的局限性;第3部分內(nèi)容說明了如果需要支持多種服務(wù)器,或是給用戶提供部署在他們自己的服務(wù)器上的獨(dú)立的web應(yīng)用的話,那么實(shí)現(xiàn)自己的Comet或是WebSocket通信系統(tǒng)會(huì)有哪些難點(diǎn),該部分內(nèi)容還討論了Socket.IO;第四部分內(nèi)容談到了Atmosphere和CometD——最知名的用于Java技術(shù)服務(wù)器的開源反向Ajax庫。
到目前為止你已經(jīng)了解了創(chuàng)建通過事件來通信的組件,在本系列的最后一部分內(nèi)容中,我們把事件驅(qū)動(dòng)開發(fā)的原則應(yīng)用到實(shí)踐中,構(gòu)建一個(gè)示例性的事件驅(qū)動(dòng)web應(yīng)用。
你可以下載本文中使用的源代碼。
前提條件
理想情況下,要充分體會(huì)本文的話,你應(yīng)該對(duì)JavaScrpit和Java有一定的了解,并且要有一些web開發(fā)經(jīng)驗(yàn)。若要運(yùn)行本文中的例子,你還需要最新版本的Maven和JDK(參見參考資料)。
術(shù)語
你可能對(duì)事件驅(qū)動(dòng)架構(gòu)(event-driven architecture,EDA)、EventBus系統(tǒng)、消息系統(tǒng)、復(fù)雜事件處理(complex event processing,CEP)和信道(channel)這些說辭并不陌生,這些術(shù)語和概念已出現(xiàn)多年。隨著技術(shù)的成熟,你可能會(huì)更頻繁地聽到這類說法。本節(jié)內(nèi)容為這些概念提供一些簡短的解釋。
事件(event)
在系統(tǒng)中會(huì)發(fā)生的一些事情的出現(xiàn),事件通常具有屬性,比如說出現(xiàn)的時(shí)間(時(shí)間戳)、來源或位置(我們點(diǎn)擊的組件),以及一些描述事件的數(shù)據(jù)。根據(jù)系統(tǒng)的不同,事件還可以有其他的一些屬性選擇。
事件驅(qū)動(dòng)架構(gòu)(Event-driven architecture,EDA)
也稱作基于事件的編程,這是一種架構(gòu)設(shè)計(jì),在這種設(shè)計(jì)中,應(yīng)用由通過發(fā)送和接收事件來通信和執(zhí)行的組件構(gòu)成。Swing的圖形化用戶界面(GUI)就是一個(gè)EDA例子,每個(gè)Swing組件都可以監(jiān)聽事件、對(duì)事件作出反應(yīng)、發(fā)送其他事件等。EDA由幾個(gè)部分組成:事件生產(chǎn)者、事件消費(fèi)者、事件和處理軟件。
1. 事件生產(chǎn)者(event producer)——該組件發(fā)出事件。在本文的例子中,表單的提交按鈕就是一個(gè)事件生產(chǎn)者。
2. 事件消費(fèi)者(event consumer)——監(jiān)聽特定事件的組件。例如,例子中的表單提交這種情況,瀏覽器監(jiān)聽表單的提交按鈕上的點(diǎn)擊操作,把表單數(shù)據(jù)發(fā)送給服務(wù)器。
3. 事件處理軟件(event-processing software)——這是系統(tǒng)的核心,事件生產(chǎn)者發(fā)布事件,事件消費(fèi)者注冊(cè)自身以接收事件。根據(jù)軟件的不同,處理過程可以很簡單(只是把接收到的事件轉(zhuǎn)發(fā)給消費(fèi)者),或很復(fù)雜(CEP)。有了CEP,軟件就可以支持各種各樣的處理方式,比如說事件的匯集、過濾和轉(zhuǎn)換等。
Esper就是這樣的一個(gè)軟件例子。事件處理軟件不僅可以表現(xiàn)成一個(gè)獨(dú)立的運(yùn)行應(yīng)用,其還可以是整合到你的應(yīng)用中的庫。
消息系統(tǒng)(messaging system)
一種事件驅(qū)動(dòng)應(yīng)用類型,在這種應(yīng)用中,事件生產(chǎn)者把消息發(fā)布到信道中,事件消費(fèi)者則通過信道進(jìn)行訂閱。事件生產(chǎn)者和消費(fèi)者彼此之間沒有鏈接,是完全獨(dú)立開來的。在這種類型的事件驅(qū)動(dòng)應(yīng)用中,通常用到的術(shù)語是消息(message)而不是事件(event)。
信道(channel)
消息系統(tǒng)中分類事件的一種方式。其代表了事件生產(chǎn)者希望事件發(fā)送到的目的地。例如,在一個(gè)聊天室應(yīng)用中,某個(gè)信道可能會(huì)是 /chatapplication/chatrooms/asdrt678,該信道標(biāo)識(shí)了一個(gè)事件生產(chǎn)者可以發(fā)送消息的特定的聊天室,圖形化的組件應(yīng)該要訂閱該信道,目的是顯示最新到達(dá)的消息。
某些消息系統(tǒng)提供了兩種類型的信道:隊(duì)列(queue)和主題(topic)。
1. 隊(duì)列(queue)——當(dāng)某條消息被發(fā)送到隊(duì)列中時(shí),只有一個(gè)事件消費(fèi)者拿到并處理該條消息,其他消費(fèi)者不會(huì)看到它。隊(duì)列可被持久化,以保證交付。最好的隊(duì)列例子是郵遞請(qǐng)求,某個(gè)web應(yīng)用在用戶注冊(cè)時(shí)發(fā)布一條消息到隊(duì)列 /myapp/mail/user-registration中,可能有多個(gè)郵件應(yīng)用訂閱了這一隊(duì)列,如果沒有的話,消息也不會(huì)丟失。
2. 主題(topic)——當(dāng)某條消息發(fā)送到某個(gè)主題上時(shí),每個(gè)訂閱者都可以接收到它,主題通常是沒有持久化的。一個(gè)例子是監(jiān)控軟件的一個(gè)主題/event/system/cpu/usage,生產(chǎn)者定期往其中發(fā)送CPU的使用情況;另一方面,這一主題可能會(huì)沒有或是有多個(gè)訂閱者,這取決于他們的興趣所在。
發(fā)布/訂閱(publish/subscribe)
事件驅(qū)動(dòng)的解決方案實(shí)現(xiàn)了發(fā)布/訂閱模式。事件生產(chǎn)者在處理軟件中發(fā)布事件,事件消費(fèi)者通過訂閱來接收它們。事件消費(fèi)者訂閱的方式依賴于軟件。在消息應(yīng)用中,它們訂閱信道(比如說,還可以有選擇地把過濾規(guī)則應(yīng)用在事件類型上)。使用諸如Esper一類的CEP,可通過類SQL的請(qǐng)求來定義你所感興趣的事件,完成訂閱操作。
為什么使用事件驅(qū)動(dòng)的解決方案
在一個(gè)傳統(tǒng)的通信方案中,如果系統(tǒng)A需要來自系統(tǒng)B的信息,就會(huì)發(fā)送一個(gè)請(qǐng)求給B。系統(tǒng)B會(huì)處理該請(qǐng)求,系統(tǒng)A則會(huì)停在那里等待響應(yīng)。在處理完成時(shí),響應(yīng)會(huì)送回給系統(tǒng)A。在這一同步的通信模式中,資源的消耗是低效的,因?yàn)樵诘却憫?yīng)時(shí)浪費(fèi)掉了處理時(shí)間。
在異步模式中,系統(tǒng)A會(huì)從系統(tǒng)B中訂閱它響應(yīng)的信息。然后系統(tǒng)A可以選擇性地給系統(tǒng)B發(fā)送通知,并立刻返回,系統(tǒng)A可以繼續(xù)處理其他事情,這一步驟是可選的。通常情況下,在事件驅(qū)動(dòng)的應(yīng)用中,你不需要請(qǐng)求其他系統(tǒng)發(fā)送事件,因?yàn)槟悴恢浪鼈兪钦l。當(dāng)系統(tǒng)B發(fā)布響應(yīng)時(shí),系統(tǒng)A會(huì)立刻接收到。
事件驅(qū)動(dòng)架構(gòu)的一個(gè)優(yōu)點(diǎn)是其允許更好的伸縮性??缮炜s性是系統(tǒng)在滿足其目標(biāo)的同時(shí)適應(yīng)需求、容量或是強(qiáng)度變化的能力。通過消除暫停時(shí)間,事件驅(qū)動(dòng)的架構(gòu)通常有著更好的表現(xiàn),以及有更高的處理效率。
另一個(gè)優(yōu)點(diǎn)表現(xiàn)在應(yīng)用的開發(fā)和維護(hù)方面。使用事件驅(qū)動(dòng)的解決方案,應(yīng)用的每個(gè)組件都可以是完全獨(dú)立和解耦的。
事件驅(qū)動(dòng)的解決方案允許有更好的反應(yīng)時(shí)間,因?yàn)橥ㄐ庞兄偷难舆t。
把事件驅(qū)動(dòng)的解決方案應(yīng)用在web上
web框架過去依賴于傳統(tǒng)的請(qǐng)求-響應(yīng)模式,這導(dǎo)致了頁面的刷新。隨著Ajax、反向Ajax以及諸如CometD和Atmosphere一類的功能強(qiáng)大的框架的出現(xiàn),現(xiàn)在把事件驅(qū)動(dòng)架構(gòu)的概念應(yīng)用到web上來獲取解耦、可伸縮性和反應(yīng)性的好處已經(jīng)不是什么難事了。
客戶端
事件驅(qū)動(dòng)架構(gòu)可應(yīng)用在GUI開發(fā)的客戶端。與創(chuàng)建一個(gè)傳統(tǒng)的web頁面不同,你可以把一個(gè)單獨(dú)的web頁面當(dāng)作容器使用。每個(gè)組件(頁面的每個(gè)組成部分)都可以是獨(dú)立的,你可以在web上放一個(gè)Java Swing GUI,就像包含了小工具(gadget)的Google頁面那樣(參見參考資料中的鏈接)。
你需要一個(gè)事件總線(event bus),例如,你需要開發(fā)一個(gè)JavaScript事件總線,其允許每個(gè)頁面組件從信道訂閱或是在信道中發(fā)布。事件也可以是異步的,在兩個(gè)或是多個(gè)事件到達(dá)后才觸發(fā)行為。事件總線可以用于頁面中的局部事件,但你也可以通過使用CometD或是Socket.IO來以插件的方式支持遠(yuǎn)端事件。
服務(wù)器端
在服務(wù)器端,你需要設(shè)置一個(gè)反向Ajax框架來支持事件驅(qū)動(dòng)的框架。在本系列前幾部分的考察中,發(fā)現(xiàn)只有CometD有著事件驅(qū)動(dòng)的方法。對(duì)于其他框架來說,你需要增加自定義的支持,這不是什么大問題。你還可以加入第三方的消息系統(tǒng),比如說JMS(例如Apache ActiveMQ)或是像Esper那樣的CEP。一個(gè)更簡單的解決方案是Redis,其支持基本的發(fā)布/訂閱。
這一文章系列談?wù)摰氖鞘录?qū)動(dòng)的web和反向Ajax,因此我們重點(diǎn)關(guān)注客戶端,不會(huì)去設(shè)置一個(gè)復(fù)雜的消息系統(tǒng)。
事件驅(qū)動(dòng)web的例子
本文將要?jiǎng)?chuàng)建的例子是一個(gè)聊天室web應(yīng)用,該應(yīng)用使用一個(gè)用戶面板來列出連接的用戶。你的用戶名是加粗顯示的,活動(dòng)用戶(20秒鐘后還處活躍狀態(tài)的那些)是綠色顯示的,20秒鐘后處于非活動(dòng)狀態(tài)的那些是橙色顯示的。如果有用戶連接或是斷開連接,列表就會(huì)刷新。
出于安全目的,web.xml文件中配置了兩分鐘的會(huì)話超時(shí),非活動(dòng)狀態(tài)兩分鐘后,就會(huì)彈出一個(gè)窗口,你會(huì)被重定向到登錄頁面。
只要你不再處于會(huì)話中或是還未連接,就會(huì)被重定向到登錄頁面。登錄頁面要求輸入用戶名并會(huì)查看是否可讓你登錄到聊天室中。
一旦登錄成功,你就可以在聊天室中給所有用戶發(fā)送消息。一個(gè)控制臺(tái)也會(huì)顯示出來,記錄所有收到的事件。
該web應(yīng)用是基于事件的,有了上述的信息,你可以很容易地定義幾個(gè)事件:
1. 用戶連接
2. 用戶斷開連接
3. 會(huì)話過期
4. 接收到聊天消息
5. 如果沒有登錄的話,安全過濾器阻攔請(qǐng)求
6. 用戶變成非活動(dòng)的
7. 用戶變成活動(dòng)的
8. 所有其他與UI協(xié)調(diào)相關(guān)的事件
某些事件只局部于web應(yīng)用,由局部總線來識(shí)別,如清單1所示:
清單1. 總線設(shè)置
bus = {
local: new EventBus({
name: ‘EventBus Local’
}),
remote: EventBus.cometd({
name: ‘EventBus Remote’,
logLevel: ‘warn’,
url: document.location.href.substring(0,
document.location.href.length -
document.location.pathname.length) + ‘/async’,
alt="" border="0" />
你可以下載這一示例應(yīng)用,許多類都是安全通道類,或是會(huì)話和用戶管理通道類。本文給出了代碼最重要的部分,不過建議你下載并運(yùn)行該應(yīng)用例子來更加深入地了解它的運(yùn)作方式。
該web應(yīng)用有不同的組件構(gòu)成:聊天室、用戶列表和控制臺(tái)。每個(gè)都很獨(dú)立,可以拿掉而不會(huì)影響到其他部分。
為了以局部的和遠(yuǎn)端的方式來設(shè)置這一事件驅(qū)動(dòng)的系統(tǒng),該例子使用了Ovea的EvenBus系統(tǒng)。其提供了一個(gè)局部的事件總線,一個(gè)活動(dòng)遠(yuǎn)端事件的ComeD橋接,以及一種協(xié)調(diào)事件的方式(在幾個(gè)事件完成之后觸發(fā)行為)。當(dāng)然,你可以選擇使用另一個(gè)不同的系統(tǒng)。該例子使用了JavaScript來進(jìn)行設(shè)置,如清單1所示。
一旦總線就位了之后,應(yīng)用和組件就是基于事件的了。在本例子中,設(shè)置的是IDLE檢測(cè)系統(tǒng),如清單2所示。
清單2. IDLE檢測(cè)系統(tǒng)
bus.local.topic(‘/event/dom/loaded’).subscribe(function() {
$.idleTimer(20000);
$(document).bind(‘idle.idleTimer’, function() {
bus.local.topic(‘/event/idle’).publish(‘inactive’);
});
$(document).bind(‘a(chǎn)ctive.idleTimer’, function() {
bus.local.topic(‘/event/idle’).publish(‘a(chǎn)ctive’);
});
})
有了清單2中的代碼,IDLE系統(tǒng)就會(huì)在檢測(cè)到活動(dòng)時(shí)發(fā)送事件。這一代碼可用在任何需要IDLE系統(tǒng)的應(yīng)用中。在該例子中,你需要在用戶活動(dòng)的遠(yuǎn)端事件中轉(zhuǎn)化一下該代碼。其也可用JavaScript來實(shí)現(xiàn),如清單3所示。
清單3. 用戶活動(dòng)管理
bus.local.topic(‘/event/idle’).subscribe(function(status) {
bus.remote.topic(‘/event/user/status/changed’).publish({
status: status == ‘a(chǎn)ctive’ ? ‘online’ : ‘a(chǎn)way’
});
});
bus.remote.topic(‘/event/user/status/changed’).subscribe(function(evt) {
if(evt.user != me.name) {
$(‘#users li’).filter(function() {
return evt.user == $(this).data(‘user’).name;
}).removeClass(‘online’)
.removeClass(‘a(chǎn)way’)
.addClass(evt.status);
}
});
首個(gè)訂閱接收來自IDLE系統(tǒng)的事件,然后把用戶狀況發(fā)送給服務(wù)器端。其他的訂閱接收來自服務(wù)器端的用戶狀況事件。因此,只要用戶的狀況發(fā)生改變,用戶列表中的用戶的顏色就會(huì)變成綠色或是橙色。
當(dāng)用戶連接或是斷開連接時(shí),就會(huì)發(fā)送一個(gè)事件,如清單4所示:
清單4. 用戶列表管理
bus.remote.topic(‘/event/user/connected’).subscribe(function(user) {
$(‘#users ul’).append(row(user));
});
bus.remote.topic(‘/event/user/disconnected’).subscribe(function(evt) {
$(‘#users li’).filter(function() {
return evt.user == $(this).data(‘user’).name;
}).remove();
});
應(yīng)用的代碼簡單、解耦且是獨(dú)立的,通過重用Ovea的許多技術(shù),你可以快速地創(chuàng)建事件驅(qū)動(dòng)的web應(yīng)用。不過,因?yàn)榭梢允褂闷渌南到y(tǒng)來代替它,因此這并不是必需的。該例子只花了一天的開發(fā)時(shí)間,其中一半的代碼都是管道代碼,包括:
1. Maven:構(gòu)建工程
2. 安全功能(登錄、退出、會(huì)話超時(shí))
3. 使用了Jersey的REST服務(wù)
結(jié)束語
該文章系列展示了如何構(gòu)建響應(yīng)式的以及是可伸縮的應(yīng)用,這些應(yīng)用能夠提供很好的用戶體驗(yàn)。事件驅(qū)動(dòng)的web應(yīng)用還是一個(gè)相當(dāng)新的概念,某些WEB框架在內(nèi)部用到了這些概念。不過本文展示的是不需要web框架來構(gòu)建的這樣的應(yīng)用,對(duì)于要分離Java開發(fā)者和web設(shè)計(jì)者之間的職責(zé)來說,使用好的、專業(yè)的庫就已是綽綽有余的了。關(guān)于如何把事件驅(qū)動(dòng)的開發(fā)變成你的日常工作的一部分,我希望你已經(jīng)有了一個(gè)較為深入的理解。它很容易讓人沉迷于其中,一旦經(jīng)過嘗試,你就不想再回退到傳統(tǒng)的框架上了。
下載
描述 名稱 大小 下載方法
文章的源代碼 reverse_ajaxpt5_source.zip 925KB HTTP
關(guān)于下載方法的說明
相關(guān)案例查看更多
相關(guān)閱讀
- 昆明小程序哪家好
- 快排推廣
- 網(wǎng)絡(luò)公司報(bào)價(jià)
- 云南小程序開發(fā)制作
- 云南做網(wǎng)站
- 云南網(wǎng)站建設(shè)快速優(yōu)化
- painter
- 云南網(wǎng)站建設(shè)高手
- 用戶登錄
- 云南小程序被騙
- 云南小程序開發(fā)報(bào)價(jià)
- 百度小程序開發(fā)
- 退款
- web開發(fā)技術(shù)
- 電商網(wǎng)站建設(shè)
- 云南百度小程序
- 微信分銷系統(tǒng)
- 網(wǎng)絡(luò)公司哪家好
- 百度推廣
- uniapp開發(fā)小程序
- 網(wǎng)站建設(shè)首頁
- 云南建站公司
- 小程序模板開發(fā)公司
- 曲靖小程序開發(fā)
- 網(wǎng)站排名優(yōu)化
- 云南建設(shè)廳網(wǎng)站首頁
- 昆明做網(wǎng)站建設(shè)的公司排名
- 網(wǎng)站建設(shè)首選公司
- 云南網(wǎng)站建設(shè)開發(fā)
- 英文網(wǎng)站建設(shè)公司