JMS(Java消息服务)入门教程
什么是Java消息服務(wù)
Java消息服務(wù)指的是兩個(gè)應(yīng)用程序之間進(jìn)行異步通信的API,它為標(biāo)準(zhǔn)消息協(xié)議和消息服務(wù)提供了一組通用接口,包括創(chuàng)建、發(fā)送、讀取消息等,用于支持JAVA應(yīng)用程序開發(fā)。在J2EE中,當(dāng)兩個(gè)應(yīng)用程序使用JMS進(jìn)行通信時(shí),它們之間并不是直接相連的,而是通過(guò)一個(gè)共同的消息收發(fā)服務(wù)連接起來(lái),可以達(dá)到解耦的效果,我們將會(huì)在接下來(lái)的教程中詳細(xì)介紹。
為什么需要JMS
在JAVA中,如果兩個(gè)應(yīng)用程序之間對(duì)各自都不了解,甚至這兩個(gè)程序可能部署在不同的大洲上,那么它們之間如何發(fā)送消息呢?舉個(gè)例子,一個(gè)應(yīng)用程序A部署在印度,另一個(gè)應(yīng)用程序部署在美國(guó),然后每當(dāng)A觸發(fā)某件事后,B想從A獲取一些更新信息。當(dāng)然,也有可能不止一個(gè)B對(duì)A的更新信息感興趣,可能會(huì)有N個(gè)類似B的應(yīng)用程序想從A中獲取更新的信息。
在這種情況下,JAVA提供了最佳的解決方案-JMS,完美解決了上面討論的問(wèn)題。
JMS同樣適用于基于事件的應(yīng)用程序,如聊天服務(wù),它需要一種發(fā)布事件機(jī)制向所有與服務(wù)器連接的客戶端發(fā)送消息。JMS與RMI不同,發(fā)送消息的時(shí)候,接收者不需要在線。服務(wù)器發(fā)送了消息,然后就不管了;等到客戶端上線的時(shí)候,能保證接收到服務(wù)器發(fā)送的消息。這是一個(gè)很強(qiáng)大的解決方案,能處理當(dāng)今世界很多普遍問(wèn)題。
JMS的優(yōu)勢(shì)
異步
JMS天生就是異步的,客戶端獲取消息的時(shí)候,不需要主動(dòng)發(fā)送請(qǐng)求,消息會(huì)自動(dòng)發(fā)送給可用的客戶端。
可靠
JMS保證消息只會(huì)遞送一次。大家都遇到過(guò)重復(fù)創(chuàng)建消息問(wèn)題,而JMS能幫你避免該問(wèn)題。
JMS消息傳送模型
在JMS API出現(xiàn)之前,大部分產(chǎn)品使用“點(diǎn)對(duì)點(diǎn)”和“發(fā)布/訂閱”中的任一方式來(lái)進(jìn)行消息通訊。JMS定義了這兩種消息發(fā)送模型的規(guī)范,它們相互獨(dú)立。任何JMS的提供者可以實(shí)現(xiàn)其中的一種或兩種模型,這是它們自己的選擇。JMS規(guī)范提供了通用接口保證我們基于JMS API編寫的程序適用于任何一種模型。
讓我們更加詳細(xì)的看下這兩種消息傳送模型:
點(diǎn)對(duì)點(diǎn)消息傳送模型
在點(diǎn)對(duì)點(diǎn)消息傳送模型中,應(yīng)用程序由消息隊(duì)列,發(fā)送者,接收者組成。每一個(gè)消息發(fā)送給一個(gè)特殊的消息隊(duì)列,該隊(duì)列保存了所有發(fā)送給它的消息(除了被接收者消費(fèi)掉的和過(guò)期的消息)。點(diǎn)對(duì)點(diǎn)消息模型有一些特性,如下:
- 每個(gè)消息只有一個(gè)接收者;
- 消息發(fā)送者和接收者并沒有時(shí)間依賴性;
- 當(dāng)消息發(fā)送者發(fā)送消息的時(shí)候,無(wú)論接收者程序在不在運(yùn)行,都能獲取到消息;
- 當(dāng)接收者收到消息的時(shí)候,會(huì)發(fā)送確認(rèn)收到通知(acknowledgement)。
發(fā)布/訂閱消息傳遞模型
在發(fā)布/訂閱消息模型中,發(fā)布者發(fā)布一個(gè)消息,該消息通過(guò)topic傳遞給所有的客戶端。在這種模型中,發(fā)布者和訂閱者彼此不知道對(duì)方,是匿名的且可以動(dòng)態(tài)發(fā)布和訂閱topic。topic主要用于保存和傳遞消息,且會(huì)一直保存消息直到消息被傳遞給客戶端。
發(fā)布/訂閱消息模型特性如下:
- 一個(gè)消息可以傳遞給多個(gè)訂閱者
- 發(fā)布者和訂閱者有時(shí)間依賴性,只有當(dāng)客戶端創(chuàng)建訂閱后才能接受消息,且訂閱者需一直保持活動(dòng)狀態(tài)以接收消息。
-
為了緩和這樣嚴(yán)格的時(shí)間相關(guān)性,JMS允許訂閱者創(chuàng)建一個(gè)可持久化的訂閱。這樣,即使訂閱者沒有被激活(運(yùn)行),它也能接收到發(fā)布者的消息。
接收消息
在JMS中,消息的接收可以使用以下兩種方式:
同步
使用同步方式接收消息的話,消息訂閱者調(diào)用receive()方法。在receive()中,消息未到達(dá)或在到達(dá)指定時(shí)間之前,方法會(huì)阻塞,直到消息可用。
異步
使用異步方式接收消息的話,消息訂閱者需注冊(cè)一個(gè)消息監(jiān)聽者,類似于事件監(jiān)聽器,只要消息到達(dá),JMS服務(wù)提供者會(huì)通過(guò)調(diào)用監(jiān)聽器的onMessage()遞送消息。
JMS編程接口
JMS應(yīng)用程序由如下基本模塊組成:
JMS管理對(duì)象
管理對(duì)象(Administered objects)是預(yù)先配置的JMS對(duì)象,由系統(tǒng)管理員為使用JMS的客戶端創(chuàng)建,主要有兩個(gè)被管理的對(duì)象:
- 連接工廠(ConnectionFactory)
- 目的地(Destination)
這兩個(gè)管理對(duì)象由JMS系統(tǒng)管理員通過(guò)使用Application Server管理控制臺(tái)創(chuàng)建,存儲(chǔ)在應(yīng)用程序服務(wù)器的JNDI名字空間或JNDI注冊(cè)表。
連接工廠(ConnectionFactory)
客戶端使用一個(gè)連接工廠對(duì)象連接到JMS服務(wù)提供者,它創(chuàng)建了JMS服務(wù)提供者和客戶端之間的連接。JMS客戶端(如發(fā)送者或接受者)會(huì)在JNDI名字空間中搜索并獲取該連接。使用該連接,客戶端能夠與目的地通訊,往隊(duì)列或話題發(fā)送/接收消息。讓我們用一個(gè)例子來(lái)理解如何發(fā)送消息:
QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF"); Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue"); Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");目的地(Destination)
目的地指明消息被發(fā)送的目的地以及客戶端接收消息的來(lái)源。JMS使用兩種目的地,隊(duì)列和話題。如下代碼指定了一個(gè)隊(duì)列和話題。
創(chuàng)建一個(gè)隊(duì)列Session
QueueSession ses = con.createQueueSession (false, Session.AUTO_ACKNOWLEDGE); //get the Queue object Queue t = (Queue) ctx.lookup ("myQueue"); //create QueueReceiver QueueReceiver receiver = ses.createReceiver(t);創(chuàng)建一個(gè)話題Session
TopicSession ses = con.createTopicSession (false, Session.AUTO_ACKNOWLEDGE); // get the Topic object Topic t = (Topic) ctx.lookup ("myTopic"); //create TopicSubscriber TopicSubscriber receiver = ses.createSubscriber(t);JMS連接
連接對(duì)象封裝了與JMS提供者之間的虛擬連接,如果我們有一個(gè)ConnectionFactory對(duì)象,可以使用它來(lái)創(chuàng)建一個(gè)連接。
Connection connection = connectionFactory.createConnection();創(chuàng)建完連接后,需要在程序使用結(jié)束后關(guān)閉它:
connection.close();JMS?會(huì)話(Session)
Session是一個(gè)單線程上下文,用于生產(chǎn)和消費(fèi)消息,可以創(chuàng)建出消息生產(chǎn)者和消息消費(fèi)者。
Session對(duì)象實(shí)現(xiàn)了Session接口,在創(chuàng)建完連接后,我們可以使用它創(chuàng)建Session。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);JMS消息生產(chǎn)者
消息生產(chǎn)者由Session創(chuàng)建,用于往目的地發(fā)送消息。生產(chǎn)者實(shí)現(xiàn)MessageProducer接口,我們可以為目的地、隊(duì)列或話題創(chuàng)建生產(chǎn)者;
MessageProducer producer = session.createProducer(dest); MessageProducer producer = session.createProducer(queue); MessageProducer producer = session.createProducer(topic);創(chuàng)建完消息生產(chǎn)者后,可以使用send方法發(fā)送消息:
producer.send(message);JMS消息消費(fèi)者
消息消費(fèi)者由Session創(chuàng)建,用于接受目的地發(fā)送的消息。消費(fèi)者實(shí)現(xiàn)MessageConsumer接口,,我們可以為目的地、隊(duì)列或話題創(chuàng)建消費(fèi)者;
MessageConsumer consumer = session.createConsumer(dest); MessageConsumer consumer = session.createConsumer(queue); MessageConsumer consumer = session.createConsumer(topic);JMS消息監(jiān)聽器
JMS消息監(jiān)聽器是消息的默認(rèn)事件處理者,他實(shí)現(xiàn)了MessageListener接口,該接口包含一個(gè)onMessage方法,在該方法中需要定義消息達(dá)到后的具體動(dòng)作。通過(guò)調(diào)用setMessageListener方法我們給指定消費(fèi)者定義了消息監(jiān)聽器
Listener myListener = new Listener(); consumer.setMessageListener(myListener);JMS消息結(jié)構(gòu)
JMS客戶端使用JMS消息與系統(tǒng)通訊,JMS消息雖然格式簡(jiǎn)單但是非常靈活, JMS消息由三部分組成:
消息頭
JMS消息頭預(yù)定義了若干字段用于客戶端與JMS提供者之間識(shí)別和發(fā)送消息,預(yù)編譯頭如下:
– JMSDestination
– JMSDeliveryMode
– JMSMessageID
– JMSTimestamp
– JMSCorrelationID
– JMSReplyTo
– JMSRedelivered
– JMSType
– JMSExpiration
– JMSPriority
消息屬性
我們可以給消息設(shè)置自定義屬性,這些屬性主要是提供給應(yīng)用程序的。對(duì)于實(shí)現(xiàn)消息過(guò)濾功能,消息屬性非常有用,JMS API定義了一些標(biāo)準(zhǔn)屬性,JMS服務(wù)提供者可以選擇性的提供部分標(biāo)準(zhǔn)屬性。
消息體
在消息體中,JMS API定義了五種類型的消息格式,讓我們可以以不同的形式發(fā)送和接受消息,并提供了對(duì)已有消息格式的兼容。不同的消息類型如下:
Text message?: javax.jms.TextMessage,表示一個(gè)文本對(duì)象。
Object message?: javax.jms.ObjectMessage,表示一個(gè)JAVA對(duì)象。
Bytes message?: javax.jms.BytesMessage,表示字節(jié)數(shù)據(jù)。
Stream message?:javax.jms.StreamMessage,表示java原始值數(shù)據(jù)流。
Map message?: javax.jms.MapMessage,表示鍵值對(duì)。
?
最后補(bǔ)充一下,常見的開源JMS服務(wù)的提供者,如下:
- JBoss 社區(qū)所研發(fā)的 HornetQ
- Joram
- Coridan的MantaRay
- The OpenJMS Group的OpenJMS
JMS使用示例
基于Tomcat + JNDI + ActiveMQ實(shí)現(xiàn)JMS的點(diǎn)對(duì)點(diǎn)消息傳送
JMS發(fā)布/訂閱消息傳送例子
譯文鏈接(做了部分修改~~)
http://howtodoinjava.com/jms/jms-java-message-service-tutorial/
?
?
以上就是JMS的入門教程,學(xué)習(xí)愉快~
?
@Author ?????風(fēng)一樣的碼農(nóng)
@HomePageUrl?http://www.cnblogs.com/chenpi/?
@Copyright ?????轉(zhuǎn)載請(qǐng)注明出處,謝謝~?
from:?https://www.cnblogs.com/chenpi/p/5559349.html?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的JMS(Java消息服务)入门教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring AOP切点表达式详解
- 下一篇: 消息中间件和JMS介绍