摘要:原文鏈接鏈接描述規(guī)范及相關(guān)實(shí)現(xiàn)是一種應(yīng)用于異步消息傳遞的標(biāo)準(zhǔn),作為平臺(tái)的一部分,可以允許不同應(yīng)用不同模塊之間實(shí)現(xiàn)可靠異步數(shù)據(jù)通信。
原文鏈接 鏈接描述
JMS規(guī)范及相關(guān)實(shí)現(xiàn)
JMS是一種應(yīng)用于異步消息傳遞的標(biāo)準(zhǔn)API,作為Java平臺(tái)的一部分,JMS可以允許不同應(yīng)用、不同模塊之間實(shí)現(xiàn)可靠、異步數(shù)據(jù)通信。
一些概念
JMS provider
An implementation of the JMS interface for a Message Oriented Middleware (MOM). Providers are implemented as either a Java JMS implementation or an adapter to a non-Java MOM.
JMS client
An application or process that produces and/or receives messages.
JMS producer/publisher
A JMS client that creates and sends messages.
JMS consumer/subscriber
A JMS client that receives messages.
JMS message
An object that contains the data being transferred between JMS clients.
JMS queue
A staging area that contains messages that have been sent and are waiting to be read. Note that, contrary to what the name queue suggests, messages don"t have to be delivered in the order sent. A JMS queue only guarantees that each message is processed only once.
JMS topic
A distribution mechanism for publishing messages that are delivered to multiple subscribers.
在JMS中,支持兩種消息模型,點(diǎn)對點(diǎn)(Point-to-point)和發(fā)布-訂閱(Publish and subscribe),這兩種模式分別對應(yīng)于JMS中的兩種消息目標(biāo)(Message Destination):隊(duì)列及主題。
在點(diǎn)對點(diǎn)模型中,每個(gè)消息都有一個(gè)發(fā)送者和一個(gè)接收者,消息中介(broker)收到發(fā)送者的消息,會(huì)將消息放入隊(duì)列中,而接收者請求并接收隊(duì)列中的一條消息后,這條消息就會(huì)從隊(duì)列中刪除。消息隊(duì)列中的每條消息只能投遞給一個(gè)接收者,但并不意味著只能使用一個(gè)接收者從隊(duì)列中取消息,根據(jù)業(yè)務(wù)需要,可以使用多個(gè)接收者同時(shí)從隊(duì)列中請求消息,分擔(dān)處理壓力。但是需要注意的是,單個(gè)接收者收到的消息是按照發(fā)送順序的,多個(gè)接收者因?yàn)槎嗑€程的關(guān)系,并不能保證收到的消息一定是原序的。
在發(fā)布-訂閱模式中,消息會(huì)發(fā)送給一個(gè)主題,但是與點(diǎn)對點(diǎn)模式不同的是消息不再只被投遞給一個(gè)接收者,而是所有此主題的訂閱者都會(huì)收到該消息。
JMS消息類型
在JMS1.1規(guī)范中,定義了五種消息類型,分別為:
1.StreamMessage :消息體是 Java 流,寫入和讀出都是順序的
2.MapMessage :消息體包含 key-value 對, key 為 String , value 為基本類型,可以通過迭代器訪問
3.TextMessage :消息體是 String
4.ObjectMessage :消息體是可序列化的 Java 對象
5.BytesMessage :消息體是字節(jié)數(shù)組
可以通過 message.clearBody() 來清除消息體;但在消費(fèi)端,消息體是只讀的,針對消息的寫操作都會(huì)拋出 MessageNotWritableException 異常
JMS消息頭
所有消息的消息頭都具體相同的字段,用于 JMS Client 以及 JMS Provider 對它們進(jìn)行區(qū)別以及進(jìn)行消息路由
1.JMSDestination
消息發(fā)送的目的地(隊(duì)列或主題);創(chuàng)建消息時(shí)可以設(shè)置 JMSDestination ,但是在發(fā)送完成時(shí)其值會(huì)更新為發(fā)送方所指定的 JMSDestination ,也就是說發(fā)送前該字段會(huì)被忽略;當(dāng)消息被消費(fèi)時(shí),該字段的值與在它被發(fā)送時(shí)被設(shè)置的值是相同的
以下所有示例均基于ActiveMQ
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建2個(gè)目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO2");
// 創(chuàng)建生產(chǎn)者
MessageProducer publisher = session.createProducer(destination);
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 創(chuàng)建消息
TextMessage message = session.createTextMessage("Test Message");
// 設(shè)置消息的目的地為destination2
message.setJMSDestination(destination2);
// 發(fā)送消息
publisher.send(message);
System.out.println(message.getJMSDestination());
代碼中,通過 message.setJMSDestination(destination2); 設(shè)置了 message 的 JMSDestination 消息頭屬性值,我們再看看其輸出結(jié)果
queue://JMS.DEMO
通過這個(gè)例子可以看出,雖然在發(fā)送前設(shè)置了消息的目的地,但是發(fā)送后消息的目的地被重置了
2.JMSDeliveryMode
指明消息的傳輸模式,有兩種:
DeliveryMode.PERSISTENT :保證消息僅傳一次, JMS Provider 服務(wù)停止后消息不會(huì)丟失;
DeliveryMode.NON_PERSISTENT :消息最多傳一次,消息會(huì)因 JMS Provider 停止后丟失;
同 JMSDestination 一樣,在發(fā)送前設(shè)置的會(huì)被忽略
看下面的例子
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建目的地
Destination destination = session.createQueue("JMS.DEMO");
// 創(chuàng)建生產(chǎn)者
MessageProducer publisher = session.createProducer(destination);
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 發(fā)送PERSISTENT消息
publisher.send(session.createTextMessage("PERSISTENT MESSAGE"));
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 發(fā)送PERSISTENT消息
publisher.send(session.createTextMessage("NON_PERSISTENT MESSAGE"));
例子中分別發(fā)送了一條 PERSISTENT 的消息和一條 NON_PERSISTENT 的消息;當(dāng) Active MQ 重啟后,啟動(dòng)消費(fèi)端,收到的消息如下
PERSISTENT MESSAGE
該例子說明,在 JMS Provider 重啟后, NON_PERSISTENT 消息丟失了,而 PERSISTENT 消息能正常被消費(fèi)者消費(fèi)
3.JMSMessageID
由 JMS Provider 指定的消息的唯一標(biāo)識(shí)符;同上面的字段一樣,在發(fā)送前設(shè)置的會(huì)被忽略,在發(fā)送完成時(shí),由 JMS Provider 重置該字段
4.JMSReplyTo
發(fā)送端在發(fā)送消息時(shí),可以指定該屬性(為一個(gè) JMSDestination ),表示期望收到客戶端的響應(yīng);是否響應(yīng)由消費(fèi)端決定
如下面的例子:
發(fā)送端:
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO3");
// 創(chuàng)建生產(chǎn)者
MessageProducer publisher = session.createProducer(destination);
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 創(chuàng)建消息
TextMessage message = session.createTextMessage("Test Message");
message.setJMSReplyTo(destination2);
// 發(fā)送消息
publisher.send(message);
接收端(可以根據(jù)情況決定是否需要回復(fù))
public void onMessage(Message message) {
try { System.out.println("Receive message: " + message); if (message.getJMSReplyTo() != null) { session.createProducer(message.getJMSReplyTo()).send(session.createTextMessage("This is a reply to"
message.getJMSReplyTo()));
} } catch (Exception e) { e.printStackTrace(); }
}
5.JMSRedelivered
當(dāng)消費(fèi)者收到帶有 JMSRedelivered 的消息頭時(shí),表明該消息在過去傳輸過但沒有被確認(rèn)
JMS Provider 必須對該字段進(jìn)行設(shè)置,當(dāng)為 true 時(shí)即告知消費(fèi)者該消息是重傳的,消費(fèi)者需要自行處理重復(fù)的消息
6.JMSExpiration
消息的過期時(shí)間,其值為當(dāng)前時(shí)間加上存活時(shí)間(毫秒);當(dāng)存活時(shí)間設(shè)置為 0 時(shí),該字段的值也被設(shè)置為 0 ,表示永不過期;
消費(fèi)端在一般情況下都不會(huì)接收到過期的消息,但 JMS Provider 并不保證這一點(diǎn);
下面的例子說明了如何設(shè)置消息的過期時(shí)間
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建目的地
Destination destination = session.createQueue("JMS.DEMO");
// 創(chuàng)建生產(chǎn)者
MessageProducer publisher = session.createProducer(destination);
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 創(chuàng)建消息
TextMessage message = session.createTextMessage("Test Message");
// 發(fā)送消息
publisher.setTimeToLive(5000);
publisher.send(message);
7.JMSPriority
消息的優(yōu)先級, 0 代表最低優(yōu)先級, 9 代表最高優(yōu)先級;一般 0~4 為普通優(yōu)先級, 5~9 為加快優(yōu)先級
JMS 規(guī)范里并沒有要求 JMS Provider 嚴(yán)格按這個(gè)優(yōu)先級來實(shí)現(xiàn),但是盡可能實(shí)現(xiàn)加快優(yōu)先級消息的傳輸在普通消息的前面
同 JMSDestination 一樣,該字段在發(fā)送前被忽略,在發(fā)送完成時(shí)重置
消息屬性
除了前面提到的消息頭以外, JMS 消息還提供了對“屬性值對”的支持,以對消息頭進(jìn)行擴(kuò)展;消息屬性主要用于消息選擇器 (message selector 詳見下文 )
1.屬性名
屬性名必須服務(wù)消息選擇器的命名規(guī)則
2.屬性值
可以是基本類型及其對象類型以及 Map 、 List 和 String
下面的例子中,消息帶 HashMap 的屬性
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建目的地
Destination destination = session.createQueue("JMS.DEMO");
// 創(chuàng)建生產(chǎn)者
MessageProducer publisher = session.createProducer(destination);
// 設(shè)置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 創(chuàng)建消息
TextMessage message = session.createTextMessage("Test Message");
// 發(fā)送消息
message.setObjectProperty("myProp", new HashMap() {
{ this.put("key1", "value1"); this.put("key2", "value2"); }
});
publisher.send(message);
3.清除屬性
JMS 不能清除單個(gè)屬性,但可以通過 Message.clearProperties() 方法清除所有消息屬性
JMS實(shí)現(xiàn)(Provider implementations)
要使用JMS,必須要有相應(yīng)的實(shí)現(xiàn)來管理session以及隊(duì)列,從Java EE1.4開始,所有的Java EE應(yīng)用服務(wù)器必須包含一個(gè)JMS實(shí)現(xiàn)。
以下是一些JMS實(shí)現(xiàn):
Apache ActiveMQ Apache Qpid, using AMQP BEA Weblogic (part of the Fusion Middleware suite) and Oracle AQ from Oracle EMS from TIBCO FFMQ, GNU LGPL licensed JBoss Messaging and HornetQ from JBoss JORAM, from the OW2 Consortium Open Message Queue, from Sun Microsystems OpenJMS, from The OpenJMS Group RabbitMQ, using AMQP Solace JMS from Solace Systems SonicMQ from Progress Software StormMQ, using AMQP SwiftMQ Tervela Ultra Messaging from 29 West (acquired by Informatica) webMethods from Software AG WebSphere Application Server from IBM, which provides an inbuilt default messaging provider known as the Service Integration Bus (SIBus), or which can connect to WebSphere MQ as a JMS provider [5] WebSphere MQ (formerly MQSeries) from IBM
Ref from:
1.http://en.wikipedia.org/wiki/Java_Messag...
2.Spring in Action
3.http://goldendoc.iteye.com/blog/1155647
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66202.html
摘要:對于與而言,則可以看做是消息傳遞技術(shù)的一種衍生或封裝。在生產(chǎn)者通知消費(fèi)者時(shí),傳遞的往往是消息或事件,而非生產(chǎn)者自身。通過消息路由,我們可以配置路由規(guī)則指定消息傳遞的路徑,以及指定具體的消費(fèi)者消費(fèi)對應(yīng)的生產(chǎn)者。采用和來進(jìn)行遠(yuǎn)程對象的通訊。 消息模式 歸根結(jié)底,企業(yè)應(yīng)用系統(tǒng)就是對數(shù)據(jù)的處理,而對于一個(gè)擁有多個(gè)子系統(tǒng)的企業(yè)應(yīng)用系統(tǒng)而言,它的基礎(chǔ)支撐無疑就是對消息的處理。與對象不同,消息本質(zhì)上...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:本文主要講述消息服務(wù)在中的使用。所以需要一個(gè)監(jiān)聽容器工廠的概念,即接口,它會(huì)引用上面創(chuàng)建好的與的連接工廠,由它來負(fù)責(zé)接收消息以及將消息分發(fā)給指定的監(jiān)聽器。為了消費(fèi)消息,訂閱者必須保持運(yùn)行的狀態(tài)。 JMS 在 SpringBoot 中的使用 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog> 本文所有服務(wù)均采用doc...
閱讀 3462·2023-04-26 00:39
閱讀 4066·2021-09-22 10:02
閱讀 2549·2021-08-09 13:46
閱讀 1106·2019-08-29 18:40
閱讀 1452·2019-08-29 18:33
閱讀 779·2019-08-29 17:14
閱讀 1520·2019-08-29 12:40
閱讀 2981·2019-08-28 18:07