java的事件模式在圖形界面領(lǐng)域的事件模式已經(jīng)有很多文章介紹,但是在服務(wù)器端我們會(huì)碰到更多的事件模式,在這里給大家總結(jié)一下:
事件直接驅(qū)動(dòng)模式
事件模式的第一個(gè)要求就是性能的要求,需要直接而且快,Command模式是必須經(jīng)常使用的,主要適合于迅速處理 前臺(tái)的命令,Command模式往往是系統(tǒng)架構(gòu)的重要部分,也是流程控制的主要模式。
Command模式經(jīng)常Java的Reflect一起使用,因?yàn)橄到y(tǒng)的事件處理系統(tǒng)是處于動(dòng)態(tài)變化的,隨著功能要求擴(kuò)展,就可能有動(dòng)態(tài)變化事件處理響應(yīng)系統(tǒng),以Struts中action為例,我們知道,StrUCts的一個(gè)主要配置文件是struts-config.xml 如下:
<struts-config>
<action-mappings>
<action path="/login" type="com.javaPRo.struts.LoginAction"/>
<action path="/logout" type="com.javapro.struts.LogoutAction"/>
</action-mappings>
</struts-config>
它實(shí)際是個(gè)command和event的映射關(guān)系,通過(guò)這個(gè)配置文件,運(yùn)行時(shí)動(dòng)態(tài)裝載相應(yīng)的Action,完成Command模式, 我們檢查L(zhǎng)oginAction代碼,就可以看出Command模式的基本特征:
public final class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
.................
}
}
很明顯,典型的Command模式需要有一個(gè)接口.接口中有一個(gè)統(tǒng)一的方法,這里統(tǒng)一的方法就是execute;
比如我們有個(gè)實(shí)時(shí)系統(tǒng),客戶(hù)段向服務(wù)器發(fā)出不同編碼代號(hào),意味著不同的請(qǐng)求,不同的請(qǐng)求有不同的Handler進(jìn)行 處理,Handler接口是:
public class Handler{
public byte[] handleRequest();
}
不同性質(zhì)的處理過(guò)程繼續(xù)這個(gè)Handler接口,如負(fù)責(zé)進(jìn)入系統(tǒng)的處理過(guò)程
public class EnterHandler implements Handler{
public byte[] handleRequest(){
//具體業(yè)務(wù)處理
......
}
}
調(diào)用Handler時(shí)是:
//從cache中獲取這個(gè)requestId對(duì)應(yīng)的Handler
Handler handler = (Handler)cache.get(new Integer(reqId));
//調(diào)用handler的統(tǒng)一方法handleRequest()
byte[] outInf = handler.handleRequest();
以上是常用的一個(gè)事件驅(qū)動(dòng)模式。它的特點(diǎn)是靠一個(gè)事件直接啟動(dòng)對(duì)應(yīng)的事件處理器。
Chain of Responsibility職責(zé)鏈模式也應(yīng)該屬于這類(lèi),當(dāng)事件到達(dá)后,讓這個(gè)事件在我們提供的一批處理器中逐個(gè)挑選適合的處理器進(jìn)行處理,這個(gè)模式缺點(diǎn)是顯然的,性能喪失在逐個(gè)挑選 上,一般不推薦使用,這個(gè)模式適合在我們無(wú)法預(yù)知發(fā)生的事件內(nèi)容時(shí)使用,因?yàn)椴恢腊l(fā)生事件的具體情況, 我們就無(wú)法在程序運(yùn)行前事先為其指派相應(yīng)的處理器,只能靠運(yùn)行時(shí),事件自己去摸索“撞運(yùn)氣”。
監(jiān)控式事件模式
監(jiān)控式事件模式就不同于事件直接驅(qū)動(dòng)模式,它是借助第三者來(lái)監(jiān)控和觸發(fā)事件,這類(lèi)事件的特點(diǎn)是: 有一個(gè)觀察者置身事外在定期獨(dú)立運(yùn)行著,我們將我們要監(jiān)聽(tīng)的事件向這個(gè)觀察者注冊(cè),這樣觀察者就 代替我們來(lái)監(jiān)聽(tīng)這個(gè)事件,應(yīng)用客戶(hù)端通過(guò)觀察者來(lái)獲得事件狀況。
應(yīng)用客戶(hù)端有三種與觀察者交互的方式:1.直接融合 2.推方式 3.拉方式。
直接融合就是說(shuō)應(yīng)用客戶(hù)端自己就是觀察者,兩者融合,這樣無(wú)疑應(yīng)用客戶(hù)端獲得的觸發(fā)時(shí)間是最快的;
推方式就是觀察者一旦偵測(cè)到事件發(fā)生,立即將事件Push推到應(yīng)用客戶(hù)端;拉方式類(lèi)似收取郵件,應(yīng)用客戶(hù)端在需要時(shí)才從觀察者拉取事件。
JDK 1.4的None Blocking I/O是監(jiān)控式事件模式的典型實(shí)現(xiàn),Selector顯然是一個(gè)監(jiān)控I/O的第三者,當(dāng)有外部事件進(jìn)來(lái),通過(guò) 調(diào)用Slector.select方法可以獲得外部事件,從而進(jìn)行處理,可參考我的本欄文章。
監(jiān)控式事件模式適合使用在觸發(fā)性質(zhì)的場(chǎng)合,比如數(shù)據(jù)庫(kù)后端觸發(fā)器 界面觸發(fā) I/O觸發(fā) 狀態(tài)改變觸發(fā)等。
我們以一個(gè)信件觸發(fā)為例,這其實(shí)是個(gè)Observer應(yīng)用例子:
比如用戶(hù)提請(qǐng)服務(wù)器計(jì)算一個(gè)數(shù)據(jù),假如用戶(hù)同時(shí)要求將計(jì)算結(jié)果向自己信箱發(fā)一封,那么我們看如何設(shè)計(jì)? 按照通常思維,這是一個(gè)次序問(wèn)題,先在內(nèi)存中計(jì)算數(shù)據(jù),然后將結(jié)果發(fā)送到他的信箱,最后返回結(jié)果到用戶(hù)端, 我們知道信件的發(fā)送是耗時(shí)的,因此,有可能網(wǎng)絡(luò)的原因造成信件發(fā)送很慢,這是用戶(hù)就一直等不到他的計(jì)算結(jié)果, 很顯然,我們使用監(jiān)控式事件模式來(lái)解決,讓發(fā)信的事件由監(jiān)控者去完成,只要需要時(shí)觸發(fā)就可以了:
public class Computer extends Observable{
public Computer(){
//將sendMailObserver設(shè)定為本類(lèi)的觀察者。
addObserver(new sendMailObserver());
}
.......
public void compute(String input,boolean needEmail,String email){
//計(jì)算操作
.........
if (needEmail){
//設(shè)置變化點(diǎn)
setChanged();
//假如需要發(fā)送email,我們把email地址作為參數(shù)傳送過(guò)去
notifyObservers(email);
}
}
}
我們?cè)賮?lái)看監(jiān)控觀察者代碼是如何寫(xiě)的?
public class sendMailObserver implements Observer{
public void update(Observable obj,Object email){
if (email instanceof String){
sendMail(email);
}
}
}
這樣服務(wù)器在執(zhí)行compute方法時(shí),就沒(méi)有發(fā)送郵件的等待,一直接繼續(xù)執(zhí)行。
監(jiān)控式事件模式和事件直接驅(qū)動(dòng)模式可以在一個(gè)系統(tǒng)一起使用,外界信號(hào)通過(guò)事件直接驅(qū)動(dòng)模式啟動(dòng)系統(tǒng)處理模塊, 系統(tǒng)處理模塊處理過(guò)程中,可以通過(guò)監(jiān)控式事件模式來(lái)觸發(fā)其它后臺(tái)任務(wù)。這樣一個(gè)架構(gòu)非常適合實(shí)時(shí)處理系統(tǒng)。
既然事件處理模式是眾多應(yīng)用系統(tǒng)的基本模式,那么應(yīng)該可以形成一個(gè)框架標(biāo)準(zhǔn),JMX的notification Model就是這樣一個(gè)架構(gòu)設(shè)計(jì)。
JMX Notification Model
我們知道,JMX是提供了一種對(duì)MBean資源執(zhí)行控制和配置的治理機(jī)制,但這只是復(fù)雜的,分布式的系統(tǒng)中的一部分, 還有需要資源能夠感應(yīng)狀態(tài)改變或者特定事件變化的機(jī)制,這就是JMX Notification Model。 在JMX Notification Model中均可以實(shí)現(xiàn)"事件直接驅(qū)動(dòng)模式"和"監(jiān)控式事件模式",這取決于你的應(yīng)用需求。
JMX Notification Model答應(yīng)MBean通過(guò)調(diào)用notifications廣播事件,接受者只要注冊(cè)為一個(gè)listerner, JMX的 MBean notification model 將會(huì)激活這個(gè)listerner注冊(cè)一次,然后將一直接受到 來(lái)自廣播者發(fā)出的各種事件。
事件模式有三個(gè)角色,第一個(gè)是事件發(fā)出者producer 然后是事件接受者Consumer,第三個(gè) 是要傳輸?shù)氖录MX notification model也是這樣分別依靠下列組件來(lái)實(shí)現(xiàn)這三個(gè)角色:
A. NotificationBroadcaster接口, 事件廣播發(fā)出者, 這個(gè)接口答應(yīng)監(jiān)聽(tīng)者在需要發(fā)出的notification中注冊(cè)他們感愛(ài)好的事件。
B. 通用事件(Notification),這是我們要傳輸?shù)氖录?Notification事件能被直接使用,也能成為子類(lèi),這些都依靠于隨同事件傳輸?shù)男畔ⅰ?通過(guò)使用通用事件類(lèi)型,監(jiān)聽(tīng)者將能接受來(lái)自廣播者所有類(lèi)型的事件。
C. NotificationListener接口, 事件監(jiān)聽(tīng)者或者接受者, 用于接受來(lái)自廣播者的任何notification信號(hào)。
D. NotificationFilter接口, 這個(gè)接口為notification的監(jiān)聽(tīng)者提供一個(gè)對(duì)發(fā)出事件的過(guò)濾器。
E. NotificationEmitter 接口, 擴(kuò)展了NotificationBroadcaster接口,當(dāng)刪除監(jiān)聽(tīng)者時(shí)答應(yīng)更多的控制功能。
只要是MBean,就既可以成為notification的發(fā)布廣播者,也可以成為notification的監(jiān)聽(tīng)者接受者,或者同時(shí)兩者都可以。
Attribute Change Notifications
Attribute Change Notifications是一種非凡的notification, 任何時(shí)候MBean屬性attribute 被修改,外界能夠被通知到。
在JMX架構(gòu)中,MBean能夠在屬性attribute變化發(fā)生時(shí),發(fā)出通知,關(guān)于診斷屬性變化的機(jī)制以及觸發(fā) 通知事件并不屬于JMX規(guī)定部分,每個(gè)MBean可以有自己獨(dú)立的實(shí)現(xiàn)方式。
Timer Service
Timer Service觸發(fā)器是在規(guī)定的日期和事件發(fā)出通知,它能夠一一個(gè)恒定的間隙不斷重復(fù)發(fā)出通知, 通知可以發(fā)往所有注冊(cè)為接受timer通知的對(duì)象,Timer Service也是一個(gè)可治理的MBean,答應(yīng)應(yīng)用系統(tǒng)設(shè)置 一個(gè)可配置的調(diào)度程度。
Monitoring
通過(guò)使用monitoring service,一個(gè)或多個(gè)MBean屬性將按規(guī)定間隔時(shí)間被監(jiān)視, 對(duì)于被觀察的Mbean,監(jiān)視器monitor將從它上面獲得一個(gè)值,叫derived gauge,這個(gè)derived gauge可以是 被觀察屬性的原值,也可以是一個(gè)數(shù)字性屬性連續(xù)被觀察值之差。
當(dāng)derived gauge值滿(mǎn)足一系列條件時(shí),每個(gè)monitor server將會(huì)發(fā)出一個(gè)特定類(lèi)型的通知。 這些條件都是在monitor被初始化時(shí)設(shè)定的,也可以通過(guò)monitor MBean的治理接口動(dòng)態(tài)設(shè)定。
根據(jù)MBean內(nèi)部屬性值類(lèi)型有三種monitor:
A.CounterMonitor - 使用Java的整數(shù)類(lèi)型來(lái)觀察屬性,有一個(gè)行為特征:
a. 總是大于或等于零.
b. 能自增.
c. 能回滾.
B.GaugeMonitor - 使用java的整數(shù)或浮點(diǎn)類(lèi)型觀察屬性。象gauge(測(cè)量?jī)x器) 要么上升 要么下降減少。
C StringMonitor - 使用String類(lèi)型觀察屬性.
事件處理架構(gòu)
JMS是基于Socket的一種消息處理框架,原理類(lèi)似于監(jiān)控式事件模式,但是JMS已經(jīng)把這種模式上升到架構(gòu)的高度。不同JVM間也依靠JMS消息可以實(shí)現(xiàn)事件系統(tǒng)(注重是系統(tǒng),不簡(jiǎn)單是一個(gè)小事件了)的觸發(fā)和激活。
從上面JMS的架構(gòu)圖可以看出事件三個(gè)角色Producer和Consumer以及事件信息本身Message.JMS就是在Producer和Consumer之間建立一個(gè)連接Connection.
JMS可實(shí)現(xiàn)同步或異步的事件觸發(fā)機(jī)制,分別是通過(guò)Poin to Point(拉方式)和Pubilsh/Subscibe(推方式)具體完成,在分布式計(jì)算環(huán)境中,異步機(jī)制是非常重要,可以起到解耦作用,因?yàn)榉植辑h(huán)境中單點(diǎn)錯(cuò)誤或通訊問(wèn)題是經(jīng)常發(fā)生的,整個(gè)分布式系統(tǒng)不能總是依靠同步機(jī)制來(lái)可靠地傳遞事件或notification.
由此可見(jiàn),事件處理模式從Java諸多架構(gòu)到我們具體應(yīng)用程序,隨處可見(jiàn),根據(jù)不同的應(yīng)用需求選擇不同的事件處理模式,才能真正挖掘Java的潛在性能。
新聞熱點(diǎn)
疑難解答
圖片精選