JMS : Java Message Service (Java消息服务)之一 [转]
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
1 引言
1.1 編寫目的
本文作為B2bi項(xiàng)目中開源產(chǎn)品JORAM的使用指導(dǎo)文檔,旨在幫助項(xiàng)目組人員方便明了的進(jìn)行JMS模塊的詳細(xì)設(shè)計(jì)和開發(fā)工作。本文檔主要包含建設(shè)銀行EAI平臺B2Bi子系統(tǒng)中使用的開源JMS產(chǎn)品??JORAM的使用說明
1.2 名詞解釋
B2Bi:
Business to Business integration (企業(yè)間集成)
JMS:
Java Message Service (Java消息服務(wù))
JORAM:
ObjectWeb的Java開源項(xiàng)目
JNDI:
Java命名和目錄接口
1.3 參考資料
《Joram-4.3-en.pdf》??JORAM使用手冊(英文)
《Joram4_0_SAMPLES.pdf》??JORAM使用舉例(英文)
《Joram4_0_ADMIN.pdf》??JORAM管理員手冊(英文)
2 JMS簡介
2.1 JMS基本概念
JMS(Java Message Service)是訪問企業(yè)消息系統(tǒng)的標(biāo)準(zhǔn)API,它便于消息系統(tǒng)中的Java應(yīng)用程序進(jìn)行消息交換,并且通過提供標(biāo)準(zhǔn)的產(chǎn)生、發(fā)送、接收消息的接口簡化企業(yè)應(yīng)用的開發(fā)。
JMS應(yīng)用由以下幾部分組成:
JMS provider :是一個消息系統(tǒng),它實(shí)現(xiàn)了JMS 接口并提供管理和控制的功能。
JMS clients :是用Java語言寫的一些程序和組件,它們產(chǎn)生和使用消息。
Messages :是在JMS clients之間傳遞的消息的對象。
Administered objects :是由使用JMS clients 的人生成的預(yù)選設(shè)置好的JMS 對象。有兩種這樣的對象:destinations和connection factories。
2.2 JMS基本功能
JMS是用于和面向消息的中間件相互通信的應(yīng)用程序接口。它既支持點(diǎn)對點(diǎn)(point-to-point)的域,又支持發(fā)布/訂閱(publish/subscribe)類型的域,并且提供對下列類型的支持:經(jīng)認(rèn)可的消息傳遞,事務(wù)型消息的傳遞,一致性消息和具有持久性的訂閱者支持。JMS還提供了另一種方式來對您的應(yīng)用與舊的后臺系統(tǒng)相集成。
2.3 消息服務(wù)類型
1) point-to-point (PTP)方式:點(diǎn)到點(diǎn)的模型。消息由一個JMS客戶機(jī)(發(fā)布者)發(fā)送到服務(wù)器上的一個目的地,即一個隊(duì)列(queue)。而另一個JMS客戶機(jī)(訂閱者)則可以訪問這個隊(duì)列,并從該服務(wù)器獲取這條消息。
point-to-point (PTP)方式有以下特點(diǎn):
a) 每一個message只有一個使用者。
b) 一個message的sender和receiver沒有時間上的依賴關(guān)系。無論sendere有沒有在運(yùn)行,Receiver都可提取message。
c) Receiver完成對message處理這后,發(fā)出確認(rèn)。
d) 當(dāng)你所發(fā)出的每一個消息必須由一個使用者成功處理的情況下,使用 PTP messaging機(jī)制。
2) publish/subscribe (pub/sub)方式:發(fā)布-訂閱模型。這里仍然是由一個JMS客戶機(jī)將一條消息發(fā)布到服務(wù)器上的一個目的地上,但是這次這個目的地叫做一個主題(topic),可有多個訂閱者去訪問該消息。消息將一直維持在主題中,直到這個主題的所有訂閱者都取走了該消息的一個副本。消息也包括了一個參數(shù),用于定義了該消息的耐久性(它能夠在服務(wù)器上等待訂閱者多長時間)。
Pub/sub messaging有如下的特點(diǎn):
a) 每一個message可以有多個使用者;
b) Publishers和subscribers在時間上有依賴關(guān)系。一個訂閱了某一個topic的客戶,只能使用在它生成訂閱之后發(fā)布的message, 并且subscriber必須一直保持活動狀態(tài)。
c) JMS API允許客戶生成持久性的訂閱,從而在某種程度上放寬了這種時間上的依賴關(guān)系,提高了靈活性處可靠性。
3) Messaging的使用
Messaging本身是異步的,使message的使用者之間沒有時間上的依賴關(guān)系。但是,JMS規(guī)范給出了更精確的定義,使Message可以以兩種方式被使用:
a) Synchronously同步:subscriber或receiver可以通過調(diào)用receive方法實(shí)時地從destination上提取message。Receive方法在收到一個 message后結(jié)束,或當(dāng)message 在一定的時間限制內(nèi)沒有收到時超時結(jié)束。
b) Asynchronously異步:客戶可以為某一個使用者注冊一個message listener。message listener和event listener很相似。當(dāng)一個message到達(dá)了destination, JMS provider通過調(diào)用listener的onMessage方法將message傳遞過去,由onMessage方法負(fù)責(zé)處理message。
更詳細(xì)的JMS規(guī)范可參考SUN相關(guān)文檔。
2.4 JMS接口類圖
2.5 JMS基本視圖
1.JMS接口描述
JMS 支持兩種消息類型PTP 和Pub/Sub,分別稱作:PTP Domain 和Pub/Sub Domain,這兩種接口都繼承統(tǒng)一的JMS父接口,JMS 主要接口如下所示:
MS父接口 PTP Pub/Sub
ConnectionFactory QueueConnectionFactory TopicConnectionFactory
Connection QueueConnection TopicConnection
Destination Queue Topic
Session QueueSession TopicSession
MessageProducer QueueSender TopicPublisher
MessageConsumer QueueReceiver,QueueBrowse r TopicSubscriber
ConnectionFactory :連接工廠,JMS 用它創(chuàng)建連接
Connection :JMS 客戶端到JMS Provider 的連接
Destination :消息的目的地
Session: 一個發(fā)送或接收消息的線程
MessageProducer: 由Session 對象創(chuàng)建的用來發(fā)送消息的對象
MessageConsumer: 由Session 對象創(chuàng)建的用來接收消息的對象
2.JMS消息模型
JMS 消息由以下幾部分組成:消息頭,屬性,消息體。
2.1 消息頭(Header) - 消息頭包含消息的識別信息和路由信息,消息頭包含一些標(biāo)準(zhǔn)的屬性如:JMSDestination,JMSMessageID 等。
消息頭 由誰設(shè)置
JMSDestination send 或 publish 方法
JMSDeliveryMode send 或 publish 方法
JMSExpiration send 或 publish 方法
JMSPriority send 或 publish 方法
JMSMessageID send 或 publish 方法
JMSTimestamp send 或 publish 方法
JMSCorrelationID 客戶
JMSReplyTo 客戶
JMSType 客戶
JMSRedelivered JMS Provider
2.2 屬性(Properties) - 除了消息頭中定義好的標(biāo)準(zhǔn)屬性外,JMS 提供一種機(jī)制增加新屬性到消息頭中,這種新屬性包含以下幾種:
1. 應(yīng)用需要用到的屬性;
2. 消息頭中原有的一些可選屬性;
3. JMS Provider 需要用到的屬性。
標(biāo)準(zhǔn)的JMS 消息頭包含以下屬性:
JMSDestination 消息發(fā)送的目的地
JMSDeliveryMode 傳遞模式, 有兩種模式: PERSISTENT 和NON_PERSISTENT,PERSISTENT 表示該消息一定要被送到目的地,否則會導(dǎo)致應(yīng)用錯誤。NON_PERSISTENT 表示偶然丟失該消息是被允許的,這兩種模式使開發(fā)者可以在消息傳遞的可靠性和吞吐量之間找到平衡點(diǎn)。
JMSMessageID 唯一識別每個消息的標(biāo)識,由JMS Provider 產(chǎn)生。
JMSTimestamp 一個消息被提交給JMS Provider 到消息被發(fā)出的時間。
JMSCorrelationID 用來連接到另外一個消息,典型的應(yīng)用是在回復(fù)消息中連接到原消息。
JMSReplyTo 提供本消息回復(fù)消息的目的地址
JMSRedelivered 如果一個客戶端收到一個設(shè)置了JMSRedelivered 屬性的消息,則表示可能該客戶端曾經(jīng)在早些時候收到過該消息,但并沒有簽收(acknowledged)。
JMSType 消息類型的識別符。
JMSExpiration 消息過期時間,等于QueueSender 的send 方法中的timeToLive 值或TopicPublisher 的publish 方法中的timeToLive 值加上發(fā)送時刻的GMT 時間值。如果timeToLive值等于零,則JMSExpiration 被設(shè)為零,表示該消息永不過期。如果發(fā)送后,在消息過期時間之后消息還沒有被發(fā)送到目的地,則該消息被清除。
JMSPriority 消息優(yōu)先級,從0-9 十個級別,0-4 是普通消息,5-9 是加急消息。JMS 不要求JMS Provider 嚴(yán)格按照這十個優(yōu)先級發(fā)送消息,但必須保證加急消息要先于普通消息到達(dá)。
2.3 消息體(Body) - JMS API 定義了5種消息體格式,也叫消息類型,你可以使用不同形式發(fā)送接收數(shù)據(jù)并可以兼容現(xiàn)有的消息格式,下面描述這5種類型:
消息類型 消息體
TextMessage java.lang.String對象,如xml文件內(nèi)容
MapMessage 名/值對的集合,名是String對象,值類型可以是Java任何基本類型
BytesMessage 字節(jié)流
StreamMessage Java中的輸入輸出流
ObjectMessage Java中的可序列化對象
Message 沒有消息體,只有消息頭和屬性
下例演示創(chuàng)建并發(fā)送一個TextMessage到一個隊(duì)列:
TextMessage message = queueSession.createTextMessage();
message.setText(msg_text); // msg_text is a String
queueSender.send(message);
下例演示接收消息并轉(zhuǎn)換為合適的消息類型:
Message m = queueReceiver.receive();
if (m instanceof TextMessage) {
TextMessage message = (TextMessage) m;
System.out.println("Reading message: " + message.getText());
} else {
// Handle error
}
3. 消息的同步異步接收
消息的同步接收是指客戶端主動去接收消息,JMS 客戶端可以采用MessageConsumer 的receive方法去接收下一個消息。
消息的異步接收是指當(dāng)消息到達(dá)時,主動通知客戶端。JMS 客戶端可以通過注冊一個實(shí) 現(xiàn)MessageListener 接口的對象到MessageConsumer,這樣,每當(dāng)消息到達(dá)時,JMS Provider 會調(diào)用MessageListener中的onMessage 方法。
4. PTP模型
PTP(Point-to-Point)模型是基于隊(duì)列的,發(fā)送方發(fā)消息到隊(duì)列,接收方從隊(duì)列接收消息,隊(duì)列的存在使得消息的異步傳輸成為可能。和郵件系統(tǒng)中的郵箱一樣,隊(duì)列可以包含各種消息,JMS Provider 提 供工具管理隊(duì)列的創(chuàng)建、刪除。JMS PTP 模型定義了客戶端如何向隊(duì)列發(fā)送消息,從隊(duì)列接收消息,瀏覽隊(duì)列中的消息。
下面描述JMS PTP 模型中的主要概念和對象:
名稱 描述
Queue 由JMS Provider 管理,隊(duì)列由隊(duì)列名識別,客戶端可以通過JNDI 接口用隊(duì)列名得到一個隊(duì)列對象。
TemporaryQueue 由QueueConnection 創(chuàng)建,而且只能由創(chuàng)建它的QueueConnection 使用。
QueueConnectionFactory 客戶端用QueueConnectionFactory 創(chuàng)建QueueConnection 對象。
QueueConnection 一個到JMS PTP provider 的連接,客戶端可以用QueueConnection 創(chuàng)建QueueSession 來發(fā)送和接收消息。
QueueSession 提供一些方法創(chuàng)建QueueReceiver 、QueueSender、QueueBrowser 和TemporaryQueue。如果在QueueSession 關(guān)閉時,有一些消息已經(jīng)被收到,但還沒有被簽收(acknowledged),那么,當(dāng)接收者下次連接到相同的隊(duì)列時,這些消息還會被再次接收。
QueueReceiver 客戶端用QueueReceiver 接收隊(duì)列中的消息,如果用戶在QueueReceiver 中設(shè)定了消息選擇條件,那么不符合條件的消息會留在隊(duì)列中,不會被接收到。
QueueSender 客戶端用QueueSender 發(fā)送消息到隊(duì)列。
QueueBrowser 客戶端可以QueueBrowser 瀏覽隊(duì)列中的消息,但不會收走消息。
QueueRequestor JMS 提供QueueRequestor 類簡化消息的收發(fā)過程。QueueRequestor 的構(gòu)造函數(shù)有兩個參數(shù):QueueSession 和queue,QueueRequestor 通過創(chuàng)建一個臨時隊(duì)列來完成最終的收發(fā)消息請求。
可靠性(Reliability) 隊(duì)列可以長久地保存消息直到接收者收到消息。接收者不需要因?yàn)閾?dān)心消息會丟失而時刻和隊(duì)列保持激活的連接狀態(tài),充分體現(xiàn)了異步傳輸模式的優(yōu)勢。
5. PUB/SUB模型
JMS Pub/Sub 模型定義了如何向一個內(nèi)容節(jié)點(diǎn)發(fā)布和訂閱消息,這些節(jié)點(diǎn)被稱作主題(topic)。
主題可以被認(rèn)為是消息的傳輸中介,發(fā)布者(publisher)發(fā)布消息到主題,訂閱者(subscribe)從主題訂閱消息。主題使得消息訂閱者和消息發(fā)布者保持互相獨(dú)立,不需要接觸即可保證消息的傳送。
下面描述JMS Pub/Sub 模型中的主要概念和對象:
名稱 描述
訂閱(subscription) 消息訂閱分為非持久訂閱(non-durable subscription)和持久訂閱(durable subscrip-tion),非持久訂閱只有當(dāng)客戶端處于激活狀態(tài),也就是和JMS Provider 保持連接狀態(tài)才能收到發(fā)送到某個主題的消息,而當(dāng)客戶端處于離線狀態(tài),這個時間段發(fā)到主題的消息將會丟失,永遠(yuǎn)不會收到。持久訂閱時,客戶端向JMS 注冊一個識別自己身份的ID,當(dāng)這個客戶端處于離線時,JMS Provider 會為這個ID 保存所有發(fā)送到主題的消息,當(dāng)客戶再次連接到JMS Provider時,會根據(jù)自己的ID 得到所有當(dāng)自己處于離線時發(fā)送到主題的消息。
Topic 主題由JMS Provider 管理,主題由主題名識別,客戶端可以通過JNDI 接口用主題名得到一個主題對象。JMS 沒有給出主題的組織和層次結(jié)構(gòu)的定義,由JMS Provider 自己定義。
TemporaryTopic 臨時主題由TopicConnection 創(chuàng)建,而且只能由創(chuàng)建它的TopicConnection 使用。臨時主題不能提供持久訂閱功能。
TopicConnectionFactory 客戶端用TopicConnectionFactory 創(chuàng)建TopicConnection 對象。
TopicConnection TopicConnection 是一個到JMS Pub/Sub provider 的連接,客戶端可以用TopicConnection創(chuàng)建TopicSession 來發(fā)布和訂閱消息。
TopicSession TopicSession 提供一些方法創(chuàng)建TopicPublisher、TopicSubscriber、TemporaryTopic 。它還提供unsubscribe 方法取消消息的持久訂閱。
TopicPublisher 客戶端用TopicPublisher 發(fā)布消息到主題。
TopicSubscriber 客戶端用TopicSubscriber 接收發(fā)布到主題上的消息。可以在TopicSubscriber 中設(shè)置消息過濾功能,這樣,不符合要求的消息不會被接收。
Durable TopicSubscriber 如果一個客戶端需要持久訂閱消息,可以使用Durable TopicSubscriber,TopSession 提供一個方法createDurableSubscriber創(chuàng)建Durable TopicSubscriber 對象。
恢復(fù)和重新派送(Recovery and Redelivery) 非持久訂閱狀態(tài)下,不能恢復(fù)或重新派送一個未簽收的消息。只有持久訂閱才能恢復(fù)或重新派送一個未簽收的消息。
TopicRequestor JMS 提供TopicRequestor 類簡化消息的收發(fā)過程。TopicRequestor 的構(gòu)造函數(shù)有兩個參數(shù):TopicSession 和topic。TopicRequestor 通過創(chuàng)建一個臨時主題來完成最終的發(fā)布和接收消息請求。
可靠性(Reliability) 當(dāng)所有的消息必須被接收,則用持久訂閱模式。當(dāng)丟失消息能夠被容忍,則用非持久訂閱模式。
3 JMS API編程模型
一個JMS應(yīng)用由以下幾個模塊組成:
3.1 Administered Objects
JMS應(yīng)用的destinations和connection factories最后是通過管理而不是編程來使用,因?yàn)椴煌膒rovider使用他們的方法不一樣。
JMS 客戶應(yīng)該使用統(tǒng)一的接口得到這些objects,從而使用JMS應(yīng)用可以運(yùn)行在不同provider上,而不需要修改或修改很少。通常管理員在JNDI上設(shè)置administered objects, 然后JMS clients 在JNDI上look up這些對象。
a) Connection Factories:
connection factory 是client用來生成與provider的connection的對象。connection factory封裝了一套由管理員定義的connection configuration參數(shù)。每個connection factory 是一個QueueConnectionFactory 或 TopicConnectionFactory接口的實(shí)例。
在JMS 客戶程序中, 通常先執(zhí)行connection factory 的JNDI API lookup。 如下例:
Context ctx = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");
TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory) ctx.lookup("TopicConnectionFactory");
如果調(diào)用不帶參數(shù)的InitialContext的lookup方法,就在當(dāng)前classpath 找jndi.properties文件。
b) Destinations:
Destination 是一個對象用于定義用戶產(chǎn)生的messages 的去向或用戶使用的messages 的來源。
在PTP里,destinations被稱作queues, 可以用下面的命令來生成它們:
Queue queue = (Queue) Queue.create("queue");
在pub/sub里, destinations被稱為topics, 可以用下面的J2EE SDK command 來生成它們:
Topic topic = (Topic) Topic.create("topic");
一個JMS應(yīng)用可以同時使用多個queues 和/或topics。
除了lookup connection factory, 也常要lookup destination。例如:
Topic myTopic = (Topic) ctx.lookup("MyTopic");
Queue myQueue = (Queue) ctx.lookup("MyQueue");
3.2 Connection
Connection封裝了一個與JMS provider的虛擬連接。Connection表示在client和provider service daemon之間打開的TCP/IP socket。可以用connection 生成一個或多個sessions。
就象connection factories, connections有兩種方式:實(shí)現(xiàn)QueueConnection或TopicConnection接口。例如, 當(dāng)有一個QueueConnectionFactory 或TopicConnectionFactory對象, 可以用他們來創(chuàng)造一個connection:
QueueConnection queueConnection =
queueConnectionFactory.createQueueConnection();
TopicConnection topicConnection =
topicConnectionFactory.createTopicConnection();
注意:當(dāng)應(yīng)用程序完成后, 必須關(guān)閉你所創(chuàng)建的connections。否則JMS provider 無法釋放資源。關(guān)閉了connection同時也關(guān)閉了sessions和message產(chǎn)生者和message使用者。
queueConnection.close();
topicConnection.close();
在使用messages前, 必須調(diào)用connection的start方法。如果要暫時停止傳送message而不關(guān)閉connection, 可以調(diào)用stop方法。
connection factory 是client用來生成與provider的connection的對象。connection factory封裝了一套由管理員定義的connection configuration參數(shù)。每個connection factory 是一個QueueConnectionFactory 或 TopicConnectionFactory接口的實(shí)例。
3.3 Session
Session是單線程的context用于產(chǎn)生和使用messages。用Session創(chuàng)建 message producers、message consumers和messages。Session管理message listeners的執(zhí)行順序。
Ssession提供事務(wù)模式,用于將一系列的sends和receives動作組合在一個工作單元里。
Session被標(biāo)記為事務(wù)模式的話,確認(rèn)消息就通過確認(rèn)和校正來自動地處理。如果session沒有標(biāo)記為事務(wù)模式,有三個用于消息確認(rèn)的選項(xiàng):
? AUTO_ACKNOWLEDGE session將自動地確認(rèn)收到一則消息。
? CLIENT_ACKNOWLEDGE 客戶端程序?qū)⒋_認(rèn)收到一則消息,調(diào)用這則消息的確認(rèn)方法。
? DUPS_OK_ACKNOWLEDGE 這個選項(xiàng)命令session“懶散的”確認(rèn)消息傳遞,可以想到,這將導(dǎo)致消息提供者傳遞的一些復(fù)制消息可能會出錯。這種確認(rèn)的方式只應(yīng)當(dāng)用于消息消費(fèi)程序可以容忍潛在的副本消息存在的情況。
Sessions, 就象connections, 也有兩種方式:實(shí)現(xiàn)QueueSession或TopicSession接口。例如:
TopicSession topicSession =
topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
第一個參數(shù)表示sessiong不實(shí)現(xiàn)事務(wù)處理; 第二個參數(shù)表示當(dāng)session成功收到messages后自動確認(rèn)。
相同的,可以用QueueConnection對象創(chuàng)建QueueSession:
QueueSession queueSession =
queueConnection.createQueueSession(true, 0);
這里, 第一個參數(shù)表示session實(shí)現(xiàn)事務(wù)處理; 第二個參數(shù)表示當(dāng)session成功收到messages后不自動確認(rèn)。
3.4 Message Producers?消息生產(chǎn)者
message producer是由session創(chuàng)建的一個對象,用于將messages傳遞到目的地。PTP方式的message producer實(shí)現(xiàn)QueueSender接口。 pub/sub方式的message producer實(shí)現(xiàn)TopicPublisher接口。
例如::
QueueSender queueSender = queueSession.createSender(myQueue);
TopicPublisher topicPublisher = topicSession.createPublisher(myTopic);
用null作為createSender或createPublisher的參數(shù),可以創(chuàng)建一個不確定的producer。用不確定的producer, 可以等到真正send或publish message的時候才指定destination
當(dāng)創(chuàng)建了一個message producer, 就可以用它來發(fā)送messages。例如:
queueSender.send(message);
topicPublisher.publish(message);
3.5 Message Consumer?消息消費(fèi)者
message consumer也是由session創(chuàng)建的一個對象,用于接收發(fā)送到目的地的消息。message consumer允許JMS client到JMS provider注冊感興趣的目的地。JMS provider管理messages從destination到注冊了這個destination的consumers之間的傳送。
PTP方式的message consumer實(shí)現(xiàn)QueueReceiver接口。pub/sub方式的message consumer實(shí)現(xiàn)TopicSubscriber接口。
例如:
QueueReceiver queueReceiver = queueSession.createReceiver(myQueue);
TopicSubscriber topicSubscriber = topicSession.createSubscriber(myTopic);
可以用TopicSession.createDurableSubscriber方法創(chuàng)建一個durable topic subscriber(異步消息訂閱 )。
當(dāng)創(chuàng)建了一個message consumer, 它就是活動的,就可以用它接收messages。可以用QueueReceiver 或TopicSubscriber的close方法把message consumer變成非活動的。Message的傳送在調(diào)用了connection的start方法后才開始。
不論是QueueReceiver或TopicSubscriber, 都可以用receive方法來同步consume message。可以在調(diào)用start方法后的任何時間調(diào)用它:
queueConnection.start();
Message m = queueReceiver.receive();
topicConnection.start();
Message m = topicSubscriber.receive(1000); // time out after a second
異步consume message, 可以使用message listener。
a) Message Listeners
message listener是一個對象,用作充當(dāng)messages的異步事件處理器。它實(shí)現(xiàn)了MessageListener接口, 它只有一個方法:onMessage。 在onMessage方法內(nèi), 可以定義當(dāng)收到一個message后做的事情。
用setMessageListener方法在某個QueueReceiver 或TopicSubscriber里注冊message listener。例如:
TopicListener topicListener = new TopicListener();
topicSubscriber.setMessageListener(topicListener);
當(dāng)注冊了message listener, 調(diào)用QueueConnection或TopicConnection的方法來開始傳送message。
當(dāng)message開始傳送, 當(dāng)有message送來,message consumer自動調(diào)用message listener的 onMessage方法。onMessage方法只有一個Message類型的參數(shù)。
message listener并不對應(yīng)特定的destination類型. 相同的listener可以從queue或topic上得到message, 這取決于listener是由QueueReceiver還是 TopicSubscriber對象設(shè)置的。然而message listener通常對應(yīng)某一個message類型或格式, 如果要回應(yīng)messages, message listener必須創(chuàng)建一個message producer。
onMessage方法應(yīng)該處理所有的exceptions。
Session負(fù)責(zé)管理message listeners的執(zhí)行順序。任何時候,只有一個message listeners在運(yùn)行。
b) Message Selectors
如果你的消息應(yīng)用程序需要過濾收到的messages, 可以用JMS API中的message selector來讓message consumer定義它所感興趣的messages。Message selectors負(fù)責(zé)過濾到JMS provider的message,而不是到應(yīng)用程序的。
message selector是一個含有表達(dá)式的字符串。表達(dá)式的語法是SQL92 conditional expression syntax的一個子集。當(dāng)創(chuàng)建message consumer時, createReceiver, createSubscriber, 和createDurableSubscriber方法都可以定義某個message selector作為參數(shù)。
message consumer只接收headers和properties與selector匹配的messages。message selector不能根據(jù)message body的內(nèi)容進(jìn)行選擇。
3.6 Message?消息組成
JMS 消息由以下幾部分組成:消息頭,屬性,消息體
消息頭(Header) - 消息頭包含消息的識別信息和路由信息,消息頭包含一些標(biāo)準(zhǔn)的屬性如:JMSDestination,JMSMessageID 等。
消息頭 由誰設(shè)置
JMSDestination send 或 publish 方法
JMSDeliveryMode send 或 publish 方法
JMSExpiration send 或 publish 方法
JMSPriority send 或 publish 方法
JMSMessageID send 或 publish 方法
JMSTimestamp send 或 publish 方法
JMSCorrelationID 客戶
JMSReplyTo 客戶
JMSType 客戶
JMSRedelivered JMS Provider
屬性(Properties) - 除了消息頭中定義好的標(biāo)準(zhǔn)屬性外,JMS 提供一種機(jī)制增加新屬性到消息頭中,這種新屬性包含以下幾種:
1. 應(yīng)用需要用到的屬性;
2. 消息頭中原有的一些可選屬性;
3. JMS Provider 需要用到的屬性。
標(biāo)準(zhǔn)的JMS 消息頭包含以下屬性:
JMSDestination --消息發(fā)送的目的地
JMSDeliveryMode --傳遞模式, 有兩種模式: PERSISTENT 和NON_PERSISTENT,PERSISTENT 表示該消息一定要被送到目的地,否則會導(dǎo)致應(yīng)用錯誤。NON_PERSISTENT 表示偶然丟失該消息是被允許的,這兩種模式使開發(fā)者可以在消息傳遞的可靠性和吞吐量之間找到平衡點(diǎn)。
JMSMessageID 唯一識別每個消息的標(biāo)識,由JMS Provider 產(chǎn)生。
JMSTimestamp 一個消息被提交給JMS Provider 到消息被發(fā)出的時間。
JMSCorrelationID 用來連接到另外一個消息,典型的應(yīng)用是在回復(fù)消息中連接到原消息。
JMSReplyTo 提供本消息回復(fù)消息的目的地址。
JMSRedelivered 如果一個客戶端收到一個設(shè)置了JMSRedelivered 屬性的消息,則表示可能該客戶端曾經(jīng)在早些時候收到過該消息,但并沒有簽收(acknowledged)。
JMSType 消息類型的識別符。
JMSExpiration 消息過期時間,等于QueueSender 的send 方法中的timeToLive 值或TopicPublisher 的publish 方法中的timeToLive 值加上發(fā)送時刻的GMT 時間值。如果timeToLive值等于零,則JMSExpiration 被設(shè)為零,表示該消息永不過期。如果發(fā)送后,在消息過期時間之后消息還沒有被發(fā)送到目的地,則該消息被清除。
JMSPriority 消息優(yōu)先級,從0-9 十個級別,0-4 是普通消息,5-9 是加急消息。JMS 不要求JMS Provider 嚴(yán)格按照這十個優(yōu)先級發(fā)送消息,但必須保證加急消息要先于普通消息到達(dá)。
消息體(Body) - JMS API 定義了5種消息體格式,也叫消息類型,你可以使用不同形式發(fā)送接收數(shù)據(jù)并可以兼容現(xiàn)有的消息格式,下面描述這5種類型:
消息類型 消息體
TextMessage java.lang.String對象,如xml文件內(nèi)容
MapMessage 名/值對的集合,名是String對象,值類型可以是Java任何基本類型
BytesMessage 字節(jié)流
StreamMessage Java中的輸入輸出流
ObjectMessage Java中的可序列化對象
Message 沒有消息體,只有消息頭和屬性。
JMS API為每一種messages都提供了一種create方法。例如:
TextMessage message = queueSession.createTextMessage();
message.setText(msg_text); // msg_text is a String
queueSender.send(message);
在使用者一端, 必須將收到的Message 按照適當(dāng)?shù)膍essage類型處理。 例如:
Message m = queueReceiver.receive();
if (m instanceof TextMessage) {
TextMessage message = (TextMessage) m;
System.out.println("Reading message: " + message.getText());
} else {
// Handle error
}
3.7 Exception Handling
JMS API的方法的Exception的根類是JMSException。JMSException類包括如下子類:
IllegalStateException
InvalidClientIDException
InvalidDestinationException
InvalidSelectorException
JMSSecurityException
MessageEOFException
MessageFormatException
MessageNotReadableException
MessageNotWriteableException
ResourceAllocationException
TransactionInProgressException
TransactionRolledBackException
4 JORAM產(chǎn)品介紹
JORAM是法國電信研究院支持的objectweb.org的開源JMS消息中間件產(chǎn)品。objectweb是一個非常活躍的開源中間件團(tuán)體。JORAM支持sun規(guī)范,實(shí)現(xiàn)JMS1.1。
4.1 Joram4.3包括
一個Message Server(消息服務(wù)器),提供Java的消息服務(wù)功能。
一個JNDI Server。
一個客戶端類,可以訪問Message Server上的消息。
一個圖形化的管理界面,配置管理Joram平臺。
4.2 系統(tǒng)要求
硬件要求:
2000年后的intel架構(gòu)pc機(jī)
256M RAM 5G硬盤
支持TCP/IP的網(wǎng)絡(luò)硬件設(shè)備
軟件要求:
操作系統(tǒng):Linux, Windows 2000 and XP, 等
網(wǎng)絡(luò)協(xié)議:TCP/IP
Java運(yùn)行環(huán)境:JDK1.4
4.3 Joram產(chǎn)品包目錄結(jié)構(gòu)
doc/ ??Joram產(chǎn)品幫助文檔
samples/ ??Joram產(chǎn)品使用舉例
bin/... ??Joram例子執(zhí)行程序
config/... ??Joram例子配置文件
class/... ??Joram例子class文件
run/... ??Joram例子運(yùn)行目錄
src/ ??Joram產(chǎn)品例子源代碼
joram/... ??J2EE環(huán)境的Joram源代碼
kjoram/… ??J2ME環(huán)境的Joram源代碼
ship/lib/... ??Joram所用的lib包
ship/licenses/... ??Joram的許可證
5 JORAM Classic Samples使用說明
Joram classic samples使用簡單的配置創(chuàng)建一個Message Server,發(fā)布一個Queue和一個Topic,并允許匿名用戶訪問。其中包口:一個消息發(fā)送的例子、一個消息發(fā)布的例子、一個標(biāo)準(zhǔn)的消息生產(chǎn)者的例子、一個消息接收的例子、一個消息訂閱的例子、一個標(biāo)準(zhǔn)的消息消費(fèi)者的例子、一個瀏覽Queue的例子。Joram平臺運(yùn)行在穩(wěn)定模式。
可以利用ant工具直接運(yùn)行Joram的上述例子
起動Joram消息Server:
ant single_server
也可以用命令行啟動Joram Server,進(jìn)入$JoramHome/samples/bin/目錄,運(yùn)行single_server.bat(win)或single_server.sh(unix)。以下操作均有類似的命令行工具。
建立Queue和Topic:
ant classic_admin
運(yùn)行Sender發(fā)送消息例子:
ant sender
運(yùn)行Receiver接受消息例子:
ant receiver
運(yùn)行Browser 瀏覽Queue例子:
ant browser
運(yùn)行消息訂約的例子:
ant subscriber
運(yùn)行消息發(fā)布的例子:
ant publisher
運(yùn)行消息消費(fèi)的例子:
ant consumer
運(yùn)行消息生產(chǎn)的例子:
ant producer
以上操作也可以利用Eclipse3.1集成開發(fā)工具,將Joram例子直接導(dǎo)入成Java工程,然后利用例子中的build.xml文件運(yùn)行。如圖:
右擊build.xml文件選擇Run As ? Ant Build...
彈出窗口如下:每個操作選項(xiàng)后面都有英文的注釋信息,說明操作的內(nèi)容,可以按照前面運(yùn)行例子的順序,依次運(yùn)行即可。
Joram Server也可以通過命令行啟動:
進(jìn)入Joram產(chǎn)品的$JORAM_HOME/samples/bin目錄,有下列批處理命令,其中.bat文件是windows環(huán)境下的命令,.sh文件是unix環(huán)境下的命令。
admin.bat? --啟動Joram圖形控制臺界面
admin.sh
classadmin.bat? --在啟動的Joram Server上創(chuàng)建去queue和topic
clean.bat? --清理Joram的運(yùn)行目錄
clean.sh
jmsclient.bat? --啟動一個JMS客戶端
jmsclient.sh
receive.bat? --啟動一個接收消息進(jìn)程
send.bat? --啟動一個發(fā)送消息進(jìn)程
single_server.bat? --啟動Joram Server
single_server.sh
sslsingle_server.bat
sslsingle_server.sh
server.sh
引文來源?? JMS : Java Message Service (Java消息服務(wù))之一 - 采云摘月 - 博客園
轉(zhuǎn)載于:https://my.oschina.net/sunjun/blog/9012
總結(jié)
以上是生活随笔為你收集整理的JMS : Java Message Service (Java消息服务)之一 [转]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 3d游戏引擎哪个好_五大开
- 下一篇: 简单的Java代码实现斗地主