JMS学习一(JMS介绍)
一、JMS是個(gè)什么
1、JMS即Java消息服務(wù)(Java Message Service)應(yīng)用程序接口,是一個(gè)Java平臺(tái)中關(guān)于面向消息中間件(MOM)的API,用于在兩個(gè)應(yīng)用程序之間,或分布式系統(tǒng)中發(fā)送消息,進(jìn)行異步通信。Java消息服務(wù)是一個(gè)與具體平臺(tái)無(wú)關(guān)的API,絕大多數(shù)MOM提供商都對(duì)JMS提供支持。
2、JMS是一組消息服務(wù)的api即接口規(guī)范即數(shù)據(jù)庫(kù)的JDBC消息服務(wù)的JMS。
二、為什么要學(xué)習(xí),使用JMS
1、在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ì)
1、異步:JMS天生就是異步的,客戶端獲取消息的時(shí)候,不需要主動(dòng)發(fā)送請(qǐng)求,消息會(huì)自動(dòng)發(fā)送給可用的客戶端。
2、可靠:JMS保證消息只會(huì)遞送一次。大家都遇到過(guò)重復(fù)創(chuàng)建消息問(wèn)題,而JMS能幫你避免該問(wèn)題,只是避免而不是杜絕,所以在一些糟糕的環(huán)境下還是有可能會(huì)出現(xiàn)重復(fù)。
四、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ì)的看下這兩種消息傳送模型;
1、點(diǎn)對(duì)點(diǎn)消息傳送模型(P2P)
在點(diǎn)對(duì)點(diǎn)消息傳送模型中,應(yīng)用程序由消息隊(duì)列,發(fā)送者,接收者組成。每一個(gè)消息發(fā)送給一個(gè)特殊的消息隊(duì)列,該隊(duì)列保存了所有發(fā)送給它的消息(除了被接收者消費(fèi)掉的和過(guò)期的消息)。
點(diǎn)對(duì)點(diǎn)消息模型有如下特性:
(1)、每個(gè)消息只有一個(gè)接受者(自己測(cè)試了一下,可以有多個(gè)接受者,但是當(dāng)有多個(gè)接收者時(shí),每個(gè)接收者只能獲取隨機(jī)的幾條信息)
(2)、消息發(fā)送者和消息接受者并沒(méi)有時(shí)間依賴性。
(3)、當(dāng)消息發(fā)送者發(fā)送消息的時(shí)候,無(wú)論接收者程序在不在運(yùn)行,都能獲取到消息;
(4)、當(dāng)接收者收到消息的時(shí)候,會(huì)發(fā)送確認(rèn)收到通知(acknowledgement)。
(5)、點(diǎn)對(duì)點(diǎn)消息模型圖:
2、發(fā)布/訂閱消息傳送模型
在發(fā)布/訂閱消息模型中,發(fā)布者發(fā)布一個(gè)消息,該消息通過(guò)topic傳遞給所有的客戶端。在這種模型中,發(fā)布者和訂閱者彼此不知道對(duì)方,是匿名的且可以動(dòng)態(tài)發(fā)布和訂閱topic。topic主要用于保存和傳遞消息,且會(huì)一直保存消息直到消息被傳遞給客戶端。
發(fā)布/訂閱消息模型有如下特性:
(1)、一個(gè)消息可以傳遞給多個(gè)訂閱者
(2)、發(fā)布者和訂閱者有時(shí)間依賴性,只有當(dāng)客戶端創(chuàng)建訂閱后才能接受消息,且訂閱者需一直保持活動(dòng)狀態(tài)以接收消息。
(3)、為了緩和這樣嚴(yán)格的時(shí)間相關(guān)性,JMS允許訂閱者創(chuàng)建一個(gè)可持久化的訂閱。這樣,即使訂閱者沒(méi)有被激活(運(yùn)行),它也能接收到發(fā)布者的消息。
(4)、發(fā)布/訂閱消息模型圖:
?
?
五、接收消息
在JMS中,消息的接收可以使用以下兩種方式:
1、同步方式:使用同步方式接收消息的話,消息訂閱者調(diào)用receive()方法。在receive()中,消息未到達(dá)或在到達(dá)指定時(shí)間之前,方法會(huì)阻塞,直到消息可用。
(1)、 目的地是Queue
?
consumer = session.createConsumer(queue); Message message = consumer.receive(); //同步方式接收?
?
(2)、目的地是Destination
?
consumer = session.createConsumer(destination); //同步方式接受信息,如果還沒(méi)有獲取到則會(huì)阻塞直到接收到信息 Message messages = consumer.receive();?
?
2、異步方式:使用異步方式接收消息的話,消息訂閱者需注冊(cè)一個(gè)消息監(jiān)聽者,類似于事件監(jiān)聽器,只要消息到達(dá),JMS服務(wù)提供者會(huì)通過(guò)調(diào)用監(jiān)聽器的onMessage()遞送消息。
異步方式接收是使用了監(jiān)聽方式:
?
?
六、JMS編程接口
JMS應(yīng)用程序由如下基本模塊組成:
1、管理對(duì)象(Administered objects)-連接工廠(Connection Factories)和目的地(Destination)
2、連接對(duì)象(Connections)
3、會(huì)話(Sessions)
4、消息生產(chǎn)者(Message Producers)
5、消息消費(fèi)者(Message Consumers)
6、消息監(jiān)聽者(Message Listeners)
7、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è)表。
8、連接工廠(ConnectionFactory)
客戶端使用一個(gè)連接工廠對(duì)象連接到JMS服務(wù)提供者,它創(chuàng)建了JMS服務(wù)提供者和客戶端之間的連接。JMS客戶端(如發(fā)送者或接受者)會(huì)在JNDI名字空間中搜索并獲取該連接。使用該連接,客戶端能夠與目的地通訊,往隊(duì)列或話題發(fā)送/接收消息。讓我們用一個(gè)例子來(lái)理解如何發(fā)送消息:
9、目的地(Destination)
目的地指明消息被發(fā)送的目的地以及客戶端接收消息的來(lái)源。JMS使用兩種目的地,隊(duì)列和話題。
10、JMS連接
連接對(duì)象封裝了與JMS提供者之間的虛擬連接,如果我們有一個(gè)ConnectionFactory對(duì)象,可以使用它來(lái)創(chuàng)建一個(gè)連接。
?
//鏈接工廠 ActiveMQConnectionFactory connectionFactory = null; //鏈接對(duì)象 Connection connection = null; connectionFactory = new ActiveMQConnectionFactory("admin","admin","tcp://192.168.1.111:61616"); connection = connectionFactory.createConnection(); connection.start();?
?
11、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。
?
?
12、JMS消息生產(chǎn)者
消息生產(chǎn)者由Session創(chuàng)建,用于往目的地發(fā)送消息。生產(chǎn)者實(shí)現(xiàn)MessageProducer接口,我們可以為目的地、隊(duì)列或話題創(chuàng)建生產(chǎn)者;
(1)、隊(duì)列(Queue)
Queue queue = session.createQueue("test_queue"); //為隊(duì)列創(chuàng)建消息生產(chǎn)者 MessageProducer producer = session.createProducer(queue);?
(2)、目的地(Destination)
Destination destination = session.createQueue("test-queue"); //為目的地創(chuàng)建消息生產(chǎn)者 MessageProducer producer = session.createProducer(destination);?
(1)(2)這兩種方式只能用在點(diǎn)對(duì)點(diǎn)消息模型
(3)、話題(Topic)
?
//創(chuàng)建話題 Topic topic = session.createTopic("myTopic.messages"); //為話題創(chuàng)建消息生產(chǎn)者 MessageProducer producer = session.createProducer(topic);?
(3)、只能用在發(fā)布/訂閱消息模型上。
? ?創(chuàng)建完消息生產(chǎn)者后,可以使用send方法發(fā)送消息:
?
13、JMS消息消費(fèi)者
消息消費(fèi)者由Session創(chuàng)建,用于接收目的地發(fā)送的消息。消費(fèi)者實(shí)現(xiàn)MessageConsumer接口,我們可以為目的地、隊(duì)列或話題創(chuàng)建消費(fèi)者;
(1)、隊(duì)列(Queue)
Queue queue = session.createQueue("test_queue"); //隊(duì)列(目的地,消費(fèi)者消費(fèi)消息的地方) MessageConsumer consumer = session.createConsumer(queue); //消息消費(fèi)者?
(2)、目的地(Destination)
//消息目的地 Destination destination = session.createQueue("test-queue"); //消息消費(fèi)者 MessageConsumer consumer = session.createConsumer(destination);?
(3)、話題(Topic)
//創(chuàng)建話題 Topic topic = session.createTopic("myTopic.messages"); //為話題創(chuàng)建消費(fèi)者 MessageConsumer consumer = session.createConsumer(topic);?
?
14、JMS消息監(jiān)聽器(消息監(jiān)聽這種方式也就是消息的異步接收方式)
JMS消息監(jiān)聽器是消息的默認(rèn)事件處理者,他實(shí)現(xiàn)了MessageListener接口,該接口包含一個(gè)onMessage方法,在該方法中需要定義消息達(dá)到后的具體動(dòng)作。通過(guò)調(diào)用setMessageListener方法我們給指定消費(fèi)者定義了消息監(jiān)聽器.
?
(1)、TextMessage
consumer.setMessageListener(new MessageListener(){ @Override public void onMessage(Message message) { TextMessage textMessage = (TextMessage)message; try { String value = textMessage.getText(); System.out.println("value: "+value); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } });?
(2)、ObjectMessage
?
?
七、JMS消息結(jié)構(gòu)
JMS客戶端使用JMS消息與系統(tǒng)通訊,JMS消息雖然格式簡(jiǎn)單但是非常靈活, JMS消息由三部分組成:
1、消息頭
JMS消息頭預(yù)定義了若干字段用于客戶端與JMS提供者之間識(shí)別和發(fā)送消息,預(yù)編譯頭如下:
–?JMSDestination?:?消息發(fā)送的目的地,主要是指Queue和Topic,由session創(chuàng)建而由生產(chǎn)者的send方法設(shè)置.
– JMSDeliveryMode:傳送模式:有兩種即久模式和非持久模式。一條持久性的消息應(yīng)該被傳輸"一次僅僅一次",這就意味著如果JMS提供者出現(xiàn)故障,該消息并不會(huì)丟失,它會(huì)在服務(wù)器恢復(fù)之后再次傳遞。一條非持久的消息最多會(huì)傳遞一次,這意味著服務(wù)器出現(xiàn)故障,該消息將永遠(yuǎn)丟失。由session穿件由消息生產(chǎn)者的send方法設(shè)置
–?JMSMessageID:唯一識(shí)別每個(gè)消息的標(biāo)識(shí),由JMS消息生產(chǎn)者產(chǎn)生。由send方法設(shè)置
–?JMSTimestamp:一個(gè)JMS Provider在調(diào)用send()方法時(shí)自動(dòng)設(shè)置,它是消息被發(fā)送和消費(fèi)者實(shí)際接收的時(shí)間差。由客戶端設(shè)置
–?JMSCorrelationID:用來(lái)連接到另外一個(gè)消息,典型的應(yīng)用是在回復(fù)消息中連接到原消息。在大多數(shù)情況下,JMSCorrelationID用于將一條消息標(biāo)記為對(duì)JMSMessageID標(biāo)示的上一條消息的應(yīng)答,不過(guò),JMSCorrelationID可以是任何值,不僅僅是JMSMessageID。由客戶端設(shè)置
–?JMSReplyTo:提供本消息回復(fù)消息的目的地址,由客戶端設(shè)置
–?JMSRedelivered:如果一個(gè)客戶端收到一個(gè)設(shè)置了JMSRedelivered屬性的消息,則表示可能客戶端曾經(jīng)在早些時(shí)候收到過(guò)該消息,但并沒(méi)有簽收(acknowledged)。如果該消息被重新傳送,JMSRedelivered=true 否則 JMSRedelivered=flase 。由JMS Provider設(shè)置
–?JMSType:消息類型的標(biāo)識(shí)符,由客戶端設(shè)置
–?JMSExpiration:消息過(guò)期時(shí)間,等于Destination的send方法中的timeToLive值加上發(fā)送時(shí)刻的GMT的時(shí)間值。如果timeToLive值等于零,則JMSExpiration被設(shè)置為零,表示該消息永不過(guò)期。如果發(fā)送后,在消息過(guò)期時(shí)間之后消息還沒(méi)有被發(fā)送到目的地,則該消息被清除。由send方法設(shè)置
–?JMSPriority:消息優(yōu)先級(jí),從0-9十個(gè)級(jí)別,0-4是普通消息,5-9是加急消息。JMS不要求JMS Provider嚴(yán)格按照這十個(gè)優(yōu)先級(jí)發(fā)送消息,但必須保證加急消息要先于普通消息到達(dá),默認(rèn)是4級(jí)。由send方法設(shè)置
一個(gè)消息的消息頭有這些屬性,我們可以按照需要對(duì)這個(gè)消息的消息進(jìn)行設(shè)計(jì),在將這個(gè)消息使用消息生產(chǎn)者的send()方法發(fā)送到消息服務(wù)上。
2、消息屬性
我們可以給消息設(shè)置自定義屬性,這些屬性主要是提供給應(yīng)用程序的。對(duì)于實(shí)現(xiàn)消息過(guò)濾功能,消息屬性非常有用,JMS API定義了一些標(biāo)準(zhǔn)屬性,JMS服務(wù)提供者可以選擇性的提供部分標(biāo)準(zhǔn)屬性。
3、消息體
在消息體中,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ì)。
總結(jié)
以上是生活随笔為你收集整理的JMS学习一(JMS介绍)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: STM32开发 -- 进制与字符串间的转
- 下一篇: STM32开发 -- DMA详解