日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[转载]使用 Apache Geronimo 和 JMS 构建事件驱动的框架

發(fā)布時(shí)間:2023/12/18 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载]使用 Apache Geronimo 和 JMS 构建事件驱动的框架 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

使用 Apache Geronimo 和 JMS 構(gòu)建事件驅(qū)動(dòng)的框架


能夠及時(shí)響應(yīng)實(shí)時(shí)信號(hào)和事件成為企業(yè)框架的最重要方面之一。本文講述了 Apache Geronimo 框架提供的技術(shù)和工具,使應(yīng)用程序和服務(wù)能夠有效地對(duì)這些信號(hào)和事件作出響應(yīng),并將其作為消息傳播到駐留在平臺(tái)虛擬層之間的相關(guān)組件中。這些技術(shù)(包括面 向服務(wù)的架構(gòu) (SOA) 和使用 Java? 反射的有效事件驅(qū)動(dòng)交互框架)有助于降低設(shè)計(jì)有效事件驅(qū)動(dòng)的軟件系統(tǒng)的復(fù)雜性,同時(shí)可以增加靈活性。

當(dāng)實(shí)時(shí)更改和事件發(fā)生時(shí),對(duì)其作出響應(yīng)是企業(yè)框架的重要需求。本文介紹了 Apache Geronimo 框架中采用的技術(shù)和機(jī)制,它們使應(yīng)用程序和服務(wù)能夠有效地響應(yīng)實(shí)時(shí)刺激,然后跨架構(gòu)虛擬層發(fā)送和接收事件。

開(kāi)發(fā)人員試圖使用傳統(tǒng)順序處理方法設(shè)計(jì)和構(gòu)建動(dòng)態(tài)工作流和集成系統(tǒng)時(shí)會(huì)遇到麻煩,因此,急需更適合的、事件感知的技術(shù)和工具。SOA 和事件驅(qū)動(dòng)的編程可以解決這一復(fù)雜的難題。

SOA 給出一個(gè)松散耦合的開(kāi)發(fā)模型和運(yùn)行時(shí)環(huán)境。它使服務(wù)提供者和服務(wù)消費(fèi)者能夠使用動(dòng)態(tài)組件交互來(lái)構(gòu)建交互模型,這些交互模型能夠利用該開(kāi)發(fā)模型靈活性和強(qiáng)大 功能。事件驅(qū)動(dòng)的交互模型比傳統(tǒng)同步機(jī)制能更及時(shí)地對(duì)動(dòng)態(tài)事件作出響應(yīng),部分原因是 SOA 中事件驅(qū)動(dòng)的編程利用分布式系統(tǒng)本身需要的許多相同特性,包括專門(mén)化、模塊化和適應(yīng)性。

事件驅(qū)動(dòng)的架構(gòu)

2003 年,Gartner Group 引入事件驅(qū)動(dòng)的架構(gòu) (EDA) 作為一種構(gòu)建系統(tǒng)、服務(wù)和應(yīng)用程序的方法,在這些所構(gòu)建的東西中,事件在松散耦合的事件接收者之間路由。事件驅(qū)動(dòng)的系統(tǒng)由事件生產(chǎn)者 和事件接收者 組成。事件生產(chǎn)者可以將事件發(fā)布到事件通道,后者可以將事件分發(fā)到訂閱事件的接收者。 與生產(chǎn)者發(fā)布事件一樣,事件通道將事件轉(zhuǎn)發(fā)給接收者。如果沒(méi)有可用的接收者,事件通道會(huì)將事件存儲(chǔ)起來(lái),然后將其轉(zhuǎn)發(fā)到稍后可用的接收者。此過(guò)程稱為存儲(chǔ)和轉(zhuǎn)發(fā)。

EDA 使用傳遞消息概念作為兩個(gè)或多個(gè)實(shí)體之間交互的方法。通過(guò)觸發(fā)對(duì)應(yīng)于某些業(yè)務(wù)領(lǐng)域事件的信號(hào)和消息,來(lái)啟動(dòng)交互。當(dāng)每個(gè)給定事件發(fā)生時(shí),會(huì)通知該事件的所有訂閱者。然后訂閱者可以對(duì)事件采取行動(dòng)。

EDA 受益于以下屬性:

  • 無(wú)耦合的關(guān)聯(lián):事件發(fā)布者和事件訂閱者預(yù)先無(wú)需知道彼此的存在。
  • 多對(duì)多的交互:一個(gè)或多個(gè)事件會(huì)影響一個(gè)或多個(gè)訂閱者。
  • 基于事件的控制流程:當(dāng)應(yīng)用程序響應(yīng)發(fā)生的事件時(shí),應(yīng)用程序流程非常自然。
  • 異步消息傳遞:業(yè)務(wù)邏輯可以隨事件同時(shí)發(fā)生。

通過(guò)圍繞 EDA 構(gòu)建應(yīng)用程序和系統(tǒng),您可以用使其更具響應(yīng)性的方式構(gòu)建它們,因?yàn)橥ㄟ^(guò)設(shè)計(jì),事件驅(qū)動(dòng)系統(tǒng)更適用于不可預(yù)知且不斷更改的環(huán)境。

事件驅(qū)動(dòng)設(shè)計(jì)和開(kāi)發(fā)的優(yōu)點(diǎn)

事件驅(qū)動(dòng)的編程有許多優(yōu)點(diǎn)。例如,此類編程可以:

  • 減少開(kāi)發(fā)和維護(hù)分布式系統(tǒng)的復(fù)雜性。
  • 使得應(yīng)用程序和服務(wù)的裝配和配置更加容易且成本更低。
  • 促進(jìn)源代碼和組件重用,從而減少 bug 并促進(jìn)敏捷的開(kāi)發(fā)和部署。

短期內(nèi),事件驅(qū)動(dòng)的設(shè)計(jì)和開(kāi)發(fā)允許更加快速、容易的定制。長(zhǎng)期內(nèi),系統(tǒng)狀態(tài)更加精確。




回頁(yè)首


EDA 和 SOA 的結(jié)合

與 順序式或過(guò)程式系統(tǒng)中客戶機(jī)必須輪詢更改請(qǐng)求不同,EDA 允許系統(tǒng)和組件在事件發(fā)生時(shí)實(shí)時(shí)動(dòng)態(tài)地作出響應(yīng)。EDA 通過(guò)引入長(zhǎng)時(shí)間運(yùn)行的處理功能來(lái)彌補(bǔ) SOA 的不足。因?yàn)槭录M(fèi)者在事件發(fā)生時(shí)接收事件,并且會(huì)調(diào)用松散耦合的服務(wù)來(lái)向客戶提供更及時(shí)更精確的數(shù)據(jù),所以對(duì)業(yè)務(wù)有益。

在 EDA 內(nèi)部,您可以跨 SOA 的各個(gè)分段(包括物理層和架構(gòu)的虛擬層)傳輸事件,這樣系統(tǒng)可以有效地作出響應(yīng)。圖 1 說(shuō)明了跨架構(gòu)堆棧各層傳播的事件。


圖 1. 跨虛擬層的傳播

正如您看到的,事件可以因應(yīng)用程序、業(yè)務(wù)、組件、平臺(tái)或系統(tǒng)層的任何更改而發(fā)生,從技術(shù)觀點(diǎn)上講,業(yè)務(wù)事件的級(jí)別自然要比系統(tǒng)事件或組件事件高。

事件的原因(事件因果關(guān)系)是理解該事件的重要因素。事件因果關(guān)系可分為水平因果關(guān)系 和垂直因果關(guān)系。當(dāng)事件發(fā)布者與事件接收者位于架構(gòu)虛擬層中的同一層時(shí),發(fā)生水平因果關(guān)系。當(dāng)事件發(fā)布者與事件接收者位于不同層時(shí),發(fā)生垂直因果關(guān)系。




回頁(yè)首


EDA 和事件隊(duì)列

事件驅(qū)動(dòng)的編程是圍繞事件生產(chǎn)者和事件消費(fèi)者之間的無(wú)耦合關(guān)系的概念構(gòu)造的。也就是說(shuō),事件消費(fèi)者不關(guān)心事件發(fā)生的地點(diǎn)或原因;而是關(guān)注事件發(fā)生后它(消費(fèi)者)將被調(diào)用。將事件生產(chǎn)者與事件消費(fèi)者隔離開(kāi)來(lái)的系統(tǒng)和應(yīng)用程序通常依賴于事件分配器或通道。此通道包含事件隊(duì)列,用作事件生產(chǎn)者和事件處理程序之間的中間層。

圖 2 說(shuō)明了生產(chǎn)者、消費(fèi)者、事件通道和主題(或隊(duì)列)之間的關(guān)系。


圖 2. 事件隊(duì)列

事件隊(duì)列的角色是存儲(chǔ)從生產(chǎn)者接收的事件,并在每個(gè)消費(fèi)者可用時(shí)將這些事件傳輸給消費(fèi)者 —— 通常是為了事件被接收。

事件隊(duì)列和主題

多數(shù)事件驅(qū)動(dòng)的系統(tǒng)依賴于預(yù)先構(gòu)建的事件隊(duì)列技術(shù),如面向消息的中間件(Message-Oriented Middleware,MOM)框架。MOM 是一種基于消息隊(duì)列的異步消息模型框架。

MOM 框架的主要優(yōu)點(diǎn)是它能夠無(wú)限期地存儲(chǔ)消息,并在消費(fèi)者準(zhǔn)備接收消息時(shí),將其路由到消費(fèi)者。MOM 按照以下消息模型工作:

  • 點(diǎn)對(duì)點(diǎn):此模型基于稱為隊(duì)列 的消息庫(kù),在該模型中,可以將消息從一個(gè)或多個(gè)生產(chǎn)者發(fā)送給單個(gè)消費(fèi)者。
  • 發(fā)布/訂閱:此模型基于稱為主題 的消息庫(kù),在該模型中,可以將消息從一個(gè)或多個(gè)生產(chǎn)者發(fā)布給一個(gè)或多個(gè)已訂閱的消費(fèi)者。

圖 3 說(shuō)明了一個(gè)發(fā)布者、事件通道、主題和多個(gè)訂閱了給定消息類型的消費(fèi)者之間的交互。


圖 3. 一個(gè)發(fā)布者、多個(gè)訂閱者、事件通道和主題之間的交互

Java 消息服務(wù) (JMS) 框架是 Java 應(yīng)用程序編程接口 (API) 在 MOM 模型上的抽象。

在 EDA 中使用 JMS

Java 技術(shù)為 Java 程序提供 JMS 作為一種普通方法,用于創(chuàng)建、發(fā)送、接收和讀取消息。JMS 是大多數(shù)消息傳遞系統(tǒng)中的常見(jiàn)概念和語(yǔ)義的接口和類抽象的框架。

通過(guò) JMS 接口,消息生產(chǎn)者和消費(fèi)者能夠以點(diǎn)對(duì)點(diǎn)或發(fā)布/訂閱模型發(fā)送和接收消息。下面的列表顯示了 JMS 中的主要組件:

  • ConnectionFactory:該對(duì)象用于創(chuàng)建 JMS 連接
  • Connection:這是到 JMS 系統(tǒng)的連接
  • Destination:消息主題或消息隊(duì)列的抽象
  • Session:發(fā)送或接收消息所在的上下文
  • MessageProducer:會(huì)話創(chuàng)建的組件,用于將消息發(fā)送到目的地
  • MessageConsumer:會(huì)話創(chuàng)建的組件,用于從目的地接收消息



回頁(yè)首


使用 Geronimo 和 JMS 的簡(jiǎn)單事件框架

Apache Geronimo 與 Active MQ 開(kāi)放源碼消息提供程序綁定在一起。Active MQ 支持 JMS,因此為圍繞 Geronimo 框架構(gòu)建的應(yīng)用程序提供一種方法來(lái)以充分利用 JMS 的消息傳遞功能。

以 下各節(jié)定義了使用 Geronimo、Active MQ 和 JMS 的概念和語(yǔ)義構(gòu)建的簡(jiǎn)單事件框架。在這些小節(jié)中定義的事件框架包括事件通道、事件發(fā)布者和事件接收者。事件通道負(fù)責(zé)注冊(cè)和取消注冊(cè)事件接收者,并負(fù)責(zé)將事 件消息從事件發(fā)布者以匿名方式路由到事件接收者。此框架給出的惟一概念是事件通道功能,即根據(jù)事件對(duì)象實(shí)現(xiàn)的 Java 類或接口的類型,來(lái)過(guò)濾消息,并將消息路由到適當(dāng)?shù)慕邮照摺?/p>

使用類/接口層次結(jié)構(gòu)過(guò)濾并路由事件

典型的消息傳遞系統(tǒng)允許消息訂閱者根據(jù)點(diǎn)號(hào)分隔的字符串(如 travel.flights.seats 或 travel.lodging.rates )來(lái)定義將接收的事件類型。本文中給出的事件框架還允許訂閱者訂閱特定類型的事件;不過(guò),該事件類型由 Java 類和接口的層次結(jié)構(gòu)定義。

事件框架可以表示為點(diǎn)號(hào)分隔的消息類型層次結(jié)構(gòu),如 圖 4 所示的類層次結(jié)構(gòu)。


圖 4. 事件應(yīng)用程序類關(guān)系

根據(jù)此圖表,訂閱 Event 接口所代表的事件的事件接收者將接收所有事件,而訂閱 FlightEvent 接口所代表的事件的事件接收者將只接收基于該接口或 FlightDelayed 類或 SeatAvailable 類的事件。此設(shè)計(jì)允許事件接收者一次訂閱多個(gè)事件類型。例如,事件接收者通過(guò)使用參數(shù) Event.class 調(diào)用事件通道的 subscribe() 方法,可以訂閱所有事件。如果添加新的事件類型,則事件接收者會(huì)在它們發(fā)布時(shí)自動(dòng)接收它們。

事件通道通過(guò)確定事件接收者訂閱的事件接口的最具體的子類型,來(lái)處理事件層次結(jié)構(gòu)。例如,清單 1 所示的 FlightDelayed 類實(shí)現(xiàn)了 FlightEvent 接口;因此,事件通道將首先查找 FlightDelayed 類的訂閱者,然后查找 FlightEvent 接口等,一直沿著類/接口層次結(jié)構(gòu)向上。


清單 1. FlightDelayed 類
class TravelEvent extends Event {}
class FlightEvent extends TravelEvent {}
class LodgingEvent extends TravelEvent {}

public class FlightDelayed
implements FlightEvent
{
private String message = "";

public FlightDelayed()
{
}

public FlightDelayed(String message)
{
this.message = message;
}

public String getMessage()
{
return message;
}

public void setMessage(String message)
{
this.message = message;
}
}

事件通道

事件通道 是事件發(fā)布者用于發(fā)布事件,事件接收者用于訂閱和接收事件的組件。簡(jiǎn)單事件通道的接口如 清單 2 所示。


清單 2. 簡(jiǎn)單事件通道的接口
public interface Channel
{
void start();

void stop();

void publish(final Event event);

void subscribe(final Receiver receiver,
final Class eventClass);

void unsubscribe(final Receiver receiver,
final Class eventClass);
}

Java 反射

Java 運(yùn)行環(huán)境 (JRE) 維護(hù)關(guān)于 java.lang.Class 類中每個(gè)類或接口的信息。Class 對(duì)象的實(shí)例給出詳細(xì)的方法簽名、字段類型、構(gòu)造器簽名、修飾符和常量。

反射 API Javadoc(參見(jiàn) 參考資料)定義了開(kāi)發(fā)人員如何以編程方式在運(yùn)行時(shí)發(fā)現(xiàn)有關(guān)類、接口、數(shù)組及諸如此類的信息。

注意,subscribe() 和 unsubscribe() 方法需要一個(gè) Class 類型的參數(shù),事件通道使用該參數(shù)來(lái)確定接收者將訂閱或取消訂閱哪些類型的事件。

為避免事件接收者輪詢事件何時(shí)發(fā)生,可以通過(guò) Receiver 接口的 receive() 方法調(diào)用事件接收者。每當(dāng)將事件發(fā)布到事件通道時(shí),都可以使用 Java 反射確定哪些訂閱者將接收該事件。然后在這些對(duì)象上調(diào)用 receive() 方法。 清單 3 顯示了一個(gè)簡(jiǎn)單事件接收者。






清單 3. 一個(gè)簡(jiǎn)單事件接收者的實(shí)現(xiàn)
public class EventReceiver
implements Receiver
{
private static final transient Log log =
LogFactory.getLog(EventReceiver.class);

private String id = "";

public EventReceiver()
{
}

public EventReceiver(String id)
{
this.id = id;
}

public void setId(String id)
{
this.id = id;
}

public String getId()
{
return id;
}

public void receive(final Event event)
{
log.info("EventReceiver [" + id
+ "] received event [" + event.getMessage() + "]");
}
}

清單 4 顯示了事件通道的一個(gè)摘錄。


清單 4. 事件通道的實(shí)現(xiàn)
public class EventChannel
implements Channel
{
private static final String TOPIC_NAME =
"java:comp/env/EventTopic";

private static final String MQ_URL = "tcp://localhost:61616";

private HashMap subscribers = new HashMap();
private TopicConnectionFactory factory = null;
private Topic eventTopic = null;
private TopicConnection topicConn = null;
private TopicSession topicSess = null;
private TopicSubscriber topicSubscriber = null;
private TopicPublisher topicPublisher = null;
private EventConsumer eventConsumer = null;

private void handleEvent(Event event)
{
final Set received = new HashSet();

for (Class eventClass = event.getClass();
Event.class.isAssignableFrom(eventClass);
eventClass = eventClass.getSuperclass())
{
ArrayList receiverList = new ArrayList();
getReceiversForEvent(getEventLeafInterface(eventClass),
receiverList);
Receiver[] receivers = new Receiver[receiverList.size()];
receiverList.toArray(receivers);
for (int i = 0; i < receivers.length; i++)
{
invokeOnce(received, receivers[i], event);
}
}
}

private void invokeOnce(Set received,
Receiver receiver,
Event event)
{
received.add(receiver);
receiver.receive(event);
}

private Class getEventLeafInterface(Class cls)
{
Class retVal = null;

if (Event.class.isAssignableFrom(cls))
{
retVal = cls;
if (cls.isInterface())
{
return retVal;
}
}

Class[] interfaces = cls.getInterfaces();
if (interfaces != null)
{
for (int i = 0; i < interfaces.length; i++)
{
if (Event.class.isAssignableFrom(interfaces[i]))
{
retVal = interfaces[i];
break;
}
retVal = getEventLeafInterface(interfaces[i]);
}
}

return retVal;
}

public void start()
{
try
{
factory = new ActiveMQConnectionFactory(MQ_URL);
topicConn = factory.createTopicConnection();
topicSess =
topicConn.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);
eventTopic = topicSess.createTopic(TOPIC_NAME);
topicSubscriber = topicSess.createSubscriber(eventTopic);
topicPublisher = topicSess.createPublisher(eventTopic);

eventConsumer = new EventConsumer(this);
Thread consumerThread = new Thread(eventConsumer);
consumerThread.setDaemon(false);
consumerThread.start();
}
catch (Exception e)
{
e.printStackTrace();
}
}

public void stop()
{
// close topic connections, sessions, consumers, etc.
}

public void publish(final Event event)
{
try
{
ObjectMessage eventMessage = topicSess.createObjectMessage();
eventMessage.setObject(event);

topicPublisher.publish(eventMessage);
}
catch (Exception e)
{
e.printStackTrace();
}
}

public void subscribe(final Receiver receiver,
final Class eventClass)
{
ArrayList receiverList = null;

Class leafCls = getEventLeafInterface(eventClass);

if (subscribers.get(leafCls) == null)
{
receiverList = new ArrayList();
subscribers.put(leafCls, receiverList);
}
else
{
receiverList = (ArrayList) subscribers.get(leafCls);
}

if (receiverList.indexOf(receiver) < 0)
{
receiverList.add(receiver);
}
}

public void unsubscribe(final Receiver receiver,
final Class eventClass)
{
Class leafCls = getEventLeafInterface(eventClass);
if (subscribers.get(leafCls) != null)
{
ArrayList receiverList = (ArrayList) subscribers.get(leafCls);
receiverList.remove(receiverList);
}
}
}

注意: EventChannel 類的完整源代碼可從本文末尾的 下載 部分通過(guò)下載獲得。

清單 5 顯示事件消費(fèi)者的實(shí)現(xiàn)摘錄。


清單 5. 事件消費(fèi)者的實(shí)現(xiàn)
class EventConsumer
implements Runnable, ExceptionListener
{
private boolean running = false;
private boolean stopped = true;
private EventChannel eventChannel = null;

private EventConsumer(EventChannel eventChannel)
{
this.eventChannel = eventChannel;
}

public void run()
{
log.info("Event Consumer started");

// Create a Topic Connection, Session, and a MessageConsumer for the Topic
// loop until stopped and distribute events to the event channel
// using the handleEvent method
eventChannel.handleEvent(event);

stopped = true;

log.info("Event Consumer stopped");
}

public void shutdown()
{
running = false;

while (stopped == false)
{
Thread.yield();
}
}
}

注意: EventConsumer 類的完整源代碼可以從本文末尾的 下載 部分通過(guò)下載獲得。

在 Geronimo 中部署和運(yùn)行事件框架

事件框架使用部署在 Geronimo 中的 Web 應(yīng)用程序來(lái)測(cè)試每個(gè)事件類型。除了事件框架外,Web 應(yīng)用程序還包括一個(gè)用于輸入事件消息的 HTML 表單和一個(gè)用于接收 HTTP 請(qǐng)求并將內(nèi)容分派到事件通道的 servlet。

HTML 表單(如 圖 5 所示)只允許將三種類型的事件消息發(fā)送到分派 servlet。


圖 5. Web 應(yīng)用程序的開(kāi)始屏幕

事件分派 servlet 實(shí)例化事件通道對(duì)象和三個(gè)示例事件接收者。事件接收者然后訂閱給定的事件,servlet 將事件發(fā)布給事件通道對(duì)象。清單 6 顯示了該 servlet。


清單 6. 分派 servlet 的實(shí)現(xiàn)
public class SenderServlet extends HttpServlet
{
private EventChannel eventChannel = null;
private EventReceiver allTravelEventReceiver = null;
private EventReceiver flightEventReceiver = null;
private EventReceiver lodgingEventReceiver = null;

public void init()
throws ServletException
{
super.init();

eventChannel = new EventChannel();
eventChannel.start();

// create event receivers
allTravelEventReceiver =
new EventReceiver("allTravelEventReceiver");
flightEventReceiver =
new EventReceiver("flightEventReceiver");
lodgingEventReceiver =
new EventReceiver("lodgingEventReceiver");

// subscribe to all Travel events
eventChannel.subscribe(allTravelEventReceiver,
TravelEvent.class);

// subscribe to Flight events
eventChannel.subscribe(flightEventReceiver,
FlightEvent.class);

// subscribe to Lodging events
eventChannel.subscribe(lodgingEventReceiver,
LodgingEvent.class);
}

public void destroy()
{
super.destroy();

// unsubscribe all event receivers and stop the event channel
}

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
// respond with input form
}

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
String txtMsg = req.getParameter("txtMsg");
if (txtMsg != null && txtMsg.length() > 0)
{
String flightDelayed = req.getParameter("FlightDelayed");
String rateIncreased = req.getParameter("RateIncreased");
String seatAvailable = req.getParameter("SeatAvailable");

if (flightDelayed != null)
{
// send a Flight event
eventChannel.publish(new FlightDelayed(txtMsg));
}
else if (rateIncreased != null)
{
// send a Lodging event
eventChannel.publish(new RateIncreased(txtMsg));
}
else if (seatAvailable != null)
{
// send a Flight event
eventChannel.publish(new SeatAvailable(txtMsg));
}
}

doGet(req, res);
}
}

注意: SenderServlet 類的完整源代碼可以從本文末尾的 下載 部分通過(guò)下載獲得。

事件分派 servlet 調(diào)用的事件框架的應(yīng)用程序流程如 圖 6 所示。


圖 6. 事件 Web 應(yīng)用程序的順序

部署應(yīng)用程序

事件框架的類和 Web 應(yīng)用程序打包在 .war 文件中,并放置在 GERONIMO_HOME/deploy 目錄下。對(duì)于創(chuàng)建并復(fù)制到 deploy 目錄下的 .war 文件,Geronimo 在啟動(dòng)時(shí)會(huì)自動(dòng)部署它。放置在 deploy 目錄下的應(yīng)用程序是熱加載的,當(dāng)發(fā)生更改時(shí),Geronimo 能夠在運(yùn)行時(shí)重新加載應(yīng)用程序。這使調(diào)試應(yīng)用程序變得非常便利。

運(yùn)行應(yīng)用程序

您可以使用位于 GERONIMO_HOME/bin 目錄下的啟動(dòng)腳本(startup.bat 或 startup.sh)啟動(dòng) Geronimo 應(yīng)用服務(wù)器。當(dāng)調(diào)用 Geronimo 啟動(dòng)腳本時(shí),會(huì)出現(xiàn) Geronimo 控制臺(tái)窗口。對(duì)于部署的事件框架的 Web 應(yīng)用程序,啟動(dòng)時(shí)出現(xiàn)的 Geronimo 控制臺(tái)窗口將包含類似于 清單 7 所示的行,確認(rèn) Web 應(yīng)用程序已成功啟動(dòng)。


清單 7. Web 應(yīng)用程序的成功啟動(dòng)
00:12:33,921 INFO [EventChannel] Starting EventChannel...
00:12:33,937 INFO [EventChannel] Creating topic connection...
00:12:35,062 INFO [EventChannel] EventChannel started
00:12:35,062 INFO [EventChannel] Event Consumer started
00:12:35,093 INFO [SenderServlet] AllTravelEventReceiver
[com.jeffhanson.eda.EventReceiver@f84033]
00:12:35,093 INFO [SenderServlet] FlightEventReceiver
[com.jeffhanson.eda.EventReceiver@3ee73b]
00:12:35,093 INFO [SenderServlet] LodgingEventReceiver
[com.jeffhanson.eda.EventReceiver@16127f4]

將事件發(fā)送給 servlet 后,servlet 會(huì)將它發(fā)布給事件通道。如果將包含文本 Flight 2365 to Detroit will be delayed 15 minutes 的 Flight-Delayed 消息發(fā)送給 servlet,則 Geronimo 控制臺(tái)窗口會(huì)顯示 類似于 清單 8 的信息。


清單 8. 成功的事件發(fā)布
00:12:53,718 INFO [SenderServlet] >>>>>
00:12:53,718 INFO [SenderServlet] >>>>>
00:12:53,734 INFO [EventChannel] Publishing event
[com.jeffhanson.eda.events.business.FlightDelayed@863854]
00:12:53,859 INFO [EventReceiver] EventReceiver [flightEventReceiver]
received event [Flight 2365 to Detroit will be delayed 15 minutes]
00:12:53,859 INFO [EventReceiver] EventReceiver [allTravelEventReceiver]
received event [Flight 2365 to Detroit will be delayed 15 minutes]




回頁(yè)首


結(jié)束語(yǔ)

設(shè) 計(jì)能夠?qū)?shí)時(shí)更改和事件作出及時(shí)響應(yīng)的有效事件驅(qū)動(dòng)軟件系統(tǒng)是一項(xiàng)復(fù)雜工作。結(jié)合使用 SOA 與使用 Java 反射的有效事件驅(qū)動(dòng)的交互框架可以減少?gòu)?fù)雜性,并增加靈活性。Geronimo 平臺(tái)提供了 API 和工具(包括 JMS 提供程序),可以用來(lái)構(gòu)建功能強(qiáng)大的事件驅(qū)動(dòng)的交互框架。

從線性企業(yè)編程轉(zhuǎn)移到面向服務(wù)的設(shè)計(jì)只能帶來(lái)適用于 SOA 模型的優(yōu)勢(shì)。重構(gòu)系統(tǒng)以獲得業(yè)務(wù)服務(wù)會(huì)導(dǎo)致服務(wù)和組件的模塊化框架。如果服務(wù)基礎(chǔ)設(shè)施的交互模型敏捷而可擴(kuò)展,那么您可以將這些組件重用于多種不同的應(yīng)用 程序。SOA、EDA 和 Apache Geronimo 為功能強(qiáng)大的有效軟件基礎(chǔ)設(shè)施提供了基礎(chǔ)。

來(lái)自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/374079/viewspace-130290/,如需轉(zhuǎn)載,請(qǐng)注明出處,否則將追究法律責(zé)任。

轉(zhuǎn)載于:http://blog.itpub.net/374079/viewspace-130290/

總結(jié)

以上是生活随笔為你收集整理的[转载]使用 Apache Geronimo 和 JMS 构建事件驱动的框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 奇米在线观看 | 国产欧美日韩三级 | 欧美一级性生活视频 | 欧美激情va永久在线播放 | 女女调教被c哭捆绑喷水百合 | 懂色av一区 | 亚洲a视频在线 | 男人天堂网在线观看 | 善良的女邻居在线观看 | 婷婷丁香综合 | 国产日本精品 | 国产图片区 | 日本一区久久 | 国产日韩三级 | 草民午夜理伦三级 | 亚洲资源在线观看 | 中文字幕精品在线 | 精品日韩在线播放 | 日本裸体动漫 | 国产精品99久久久久久一二区 | 国产特级黄色片 | 国产精品久久久久无码av | 麻豆视频播放 | 能看av的网址 | 亚洲一区在线免费 | 999久久久久| 国产精品亚洲综合 | 色婷婷婷 | 国产一级片麻豆 | 国产美女在线观看 | 日本黄色高清 | 亲子乱对白乱都乱了 | 黑人糟蹋人妻hd中文字幕 | 国产 福利 在线 | 另类av小说 | 黄色大全免费观看 | 美女性高潮视频 | 亚洲妇熟xx妇色黄蜜桃 | 在线日韩视频 | 国产精品啪啪啪视频 | 日韩一级在线播放 | 久久精品视频免费播放 | 欧美一级黄色网 | 四虎黄色网 | 欧美色xxxxx| 午夜啪啪福利 | 少妇性l交大片免潘金莲 | 香港台湾日本三级大全 | 欧美伊人久久 | 欧美成人三级在线 | 欧美性视频在线播放 | 伊人二区| av网页在线观看 | 激情综| 综合激情网站 | 男朋友是消防员第一季 | 色婷婷狠狠18禁久久 | 靠逼视频免费网站 | 红桃视频成人 | 亚洲性天堂| 日韩精品一区二区三区在线观看 | 国内视频精品 | 国产中年熟女高潮大集合 | 久久黑人 | 亚洲色图国产视频 | 一个色在线视频 | 夜色网| 一区二区高清 | 免费小视频在线观看 | 欧美性生交xxxxx | 婷婷综合久久 | 久久国产一区二区三区 | 在线播放免费av | 亚洲乱乱 | 黄色成人免费观看 | 91成人在线观看喷潮动漫 | 亚洲卡一| 性欧美18一19内谢 | 欧美1页| 久久免费精彩视频 | av资源部| 日本亚洲最大的色成网站www | 九九黄色片 | 一色道久久88加勒比一 | 免费91视频 | xx99小雪 | 中文字幕Av日韩精品 | 超碰在线一区 | 亚洲综合精品国产 | 美女免费福利视频 | 欧美 日韩 国产 一区 | 人人爽人人爽人人 | 午夜免费小视频 | 欧美日韩一区二区不卡 | 精品国产一二区 | 亚洲精品福利网站 | 三级视频久久 | 用舌头去添高潮无码视频 | 少妇的激情 |