JMS 入門

一垂寥、JMS是個什么

  1. JMS即Java消息服務(wù)(Java Message Service)應(yīng)用程序接口牌捷,是一個Java平臺中關(guān)于面向消息中間件(MOM)的API亲桥,用于在兩個應(yīng)用程序之間柑晒,或分布式系統(tǒng)中發(fā)送消息,進行異步通信囚衔。Java消息服務(wù)是一個與具體平臺無關(guān)的API铝穷,絕大多數(shù)MOM提供商都對JMS提供支持。

2佳魔、JMS是一組消息服務(wù)的api即接口規(guī)范

二、為什么要學(xué)習(xí)晦炊,使用JMS
1鞠鲜、在JAVA中,如果兩個應(yīng)用程序之間對各自都不了解断国,甚至這兩個程序可能部署在不同的大洲上贤姆,那么它們之間如何發(fā)送消息呢?舉個例子稳衬,一個應(yīng)用程序A部署在印度霞捡,另一個應(yīng)用程序部署在美國,然后每當(dāng)A觸發(fā)某件事后薄疚,B想從A獲取一些更新信息碧信。當(dāng)然,也有可能不止一個B對A的更新信息感興趣街夭,可能會有N個類似B的應(yīng)用程序想從A中獲取更新的信息砰碴。在這種情況下,JAVA提供了最佳的解決方案-JMS板丽,完美解決了上面討論的問題呈枉。JMS同樣適用于基于事件的應(yīng)用程序,如聊天服務(wù)埃碱,它需要一種發(fā)布事件機制向所有與服務(wù)器連接的客戶端發(fā)送消息猖辫。JMS與RMI不同,發(fā)送消息的時候砚殿,接收者不需要在線啃憎。服務(wù)器發(fā)送了消息,然后就不管了瓮具;等到客戶端上線的時候荧飞,能保證接收到服務(wù)器發(fā)送的消息。這是一個很強大的解決方案名党,能處理當(dāng)今世界很多普遍問題叹阔。

三、JMS有什么優(yōu)勢

1传睹、異步:JMS天生就是異步的耳幢,客戶端獲取消息的時候,不需要主動發(fā)送請求,消息會自動發(fā)送給可用的客戶端睛藻。

2启上、可靠:JMS保證消息只會遞送一次。大家都遇到過重復(fù)創(chuàng)建消息問題店印,而JMS能幫你避免該問題冈在,只是避免而不是杜絕,所以在一些糟糕的環(huán)境下還是有可能會出現(xiàn)重復(fù)按摘。

四包券、JMS消息傳送模型

在JMS API出現(xiàn)之前,大部分產(chǎn)品使用“點對點”和“發(fā)布/訂閱”中的任一方式來進行消息通訊炫贤。JMS定義了這兩種消息發(fā)送模型的規(guī)范溅固,它們相互獨立。任何JMS的提供者可以實現(xiàn)其中的一種或兩種模型兰珍,這是它們自己的選擇侍郭。JMS規(guī)范提供了通用接口保證我們基于JMS API編寫的程序適用于任何一種模型。讓我們更加詳細(xì)的看下這兩種消息傳送模型;

1掠河、點對點消息傳送模型(P2P)

在點對點消息傳送模型中亮元,應(yīng)用程序由消息隊列,發(fā)送者口柳,接收者組成苹粟。每一個消息發(fā)送給一個特殊的消息隊列,該隊列保存了所有發(fā)送給它的消息(除了被接收者消費掉的和過期的消息)跃闹。

點對點消息模型有如下特性:
(1)嵌削、每個消息只有一個接受者(自己測試了一下,可以有多個接受者望艺,但是當(dāng)有多個接收者時苛秕,每個接收者只能獲取隨機的幾條信息)

(2)、消息發(fā)送者和消息接受者并沒有時間依賴性找默。

(3)艇劫、當(dāng)消息發(fā)送者發(fā)送消息的時候,無論接收者程序在不在運行惩激,都能獲取到消息店煞;

(4)、當(dāng)接收者收到消息的時候风钻,會發(fā)送確認(rèn)收到通知(acknowledgement)顷蟀。

(5)、點對點消息模型圖:


20170215224417110.gif

2骡技、發(fā)布/訂閱消息傳送模型

在發(fā)布/訂閱消息模型中鸣个,發(fā)布者發(fā)布一個消息羞反,該消息通過topic傳遞給所有的客戶端。在這種模型中囤萤,發(fā)布者和訂閱者彼此不知道對方昼窗,是匿名的且可以動態(tài)發(fā)布和訂閱topic。topic主要用于保存和傳遞消息涛舍,且會一直保存消息直到消息被傳遞給客戶端澄惊。

發(fā)布/訂閱消息模型有如下特性:

(1)、一個消息可以傳遞給多個訂閱者

(2)富雅、發(fā)布者和訂閱者有時間依賴性缤削,只有當(dāng)客戶端創(chuàng)建訂閱后才能接受消息,且訂閱者需一直保持活動狀態(tài)以接收消息吹榴。

(3)、為了緩和這樣嚴(yán)格的時間相關(guān)性滚婉,JMS允許訂閱者創(chuàng)建一個可持久化的訂閱图筹。這樣,即使訂閱者沒有被激活(運行)让腹,它也能接收到發(fā)布者的消息远剩。

(4)、發(fā)布/訂閱消息模型圖:


20170215224810143.gif

五骇窍、接收消息

在JMS中瓜晤,消息的接收可以使用以下兩種方式:

1、同步方式:使用同步方式接收消息的話腹纳,消息訂閱者調(diào)用receive()方法痢掠。在receive()中,消息未到達或在到達指定時間之前嘲恍,方法會阻塞足画,直到消息可用。

1)佃牛、 目的地是Queue

 consumer = session.createConsumer(queue);  
 Message message = consumer.receive(); //同步方式接收

(2)淹辞、目的地是Destination

consumer = session.createConsumer(destination);  
//同步方式接受信息,如果還沒有獲取到則會阻塞直到接收到信息  
Message messages = consumer.receive();  

2、異步方式:使用異步方式接收消息的話俘侠,消息訂閱者需注冊一個消息監(jiān)聽者象缀,類似于事件監(jiān)聽器,只要消息到達爷速,JMS服務(wù)提供者會通過調(diào)用監(jiān)聽器的onMessage()遞送消息央星。

異步方式接收是使用了監(jiān)聽方式:

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();  
                        }  
                    }  
                });  

六、JMS編程接口

JMS應(yīng)用程序由如下基本模塊組成:

1遍希、管理對象(Administered objects)-連接工廠(Connection Factories)和目的地(Destination)
2等曼、連接對象(Connections)
3、會話(Sessions)
4、消息生產(chǎn)者(Message Producers)
5禁谦、消息消費者(Message Consumers)
6胁黑、消息監(jiān)聽者(Message Listeners)

20170215230025420.png

7、JMS管理對象

管理對象(Administered objects)是預(yù)先配置的JMS對象州泊,由系統(tǒng)管理員為使用JMS的客戶端創(chuàng)建丧蘸,主要有兩個被管理的對象:
連接工廠(ConnectionFactory)
目的地(Destination)
這兩個管理對象由JMS系統(tǒng)管理員通過使用Application Server管理控制臺創(chuàng)建,存儲在應(yīng)用程序服務(wù)器的JNDI名字空間或JNDI注冊表遥皂。

8力喷、連接工廠(ConnectionFactory)

客戶端使用一個連接工廠對象連接到JMS服務(wù)提供者,它創(chuàng)建了JMS服務(wù)提供者和客戶端之間的連接演训。JMS客戶端(如發(fā)送者或接受者)會在JNDI名字空間中搜索并獲取該連接弟孟。使用該連接,客戶端能夠與目的地通訊样悟,往隊列或話題發(fā)送/接收消息拂募。讓我們用一個例子來理解如何發(fā)送消息:

9、目的地(Destination)

目的地指明消息被發(fā)送的目的地以及客戶端接收消息的來源窟她。JMS使用兩種目的地陈症,隊列和話題。

10震糖、JMS連接

連接對象封裝了與JMS提供者之間的虛擬連接录肯,如果我們有一個ConnectionFactory對象,可以使用它來創(chuàng)建一個連接吊说。

//鏈接工廠  
        ActiveMQConnectionFactory connectionFactory = null;  
        //鏈接對象  
        Connection connection = null;  
connectionFactory = new ActiveMQConnectionFactory("admin","admin","tcp://192.168.1.111:61616");  
connection = connectionFactory.createConnection();  
            connection.start();  

11论咏、JMS 會話(Session)

Session是一個單線程上下文,用于生產(chǎn)和消費消息颁井,可以創(chuàng)建出消息生產(chǎn)者和消息消費者潘靖。
Session對象實現(xiàn)了Session接口,在創(chuàng)建完連接后蚤蔓,我們可以使用它創(chuàng)建Session卦溢。

            //第一個參數(shù)是否開啟事務(wù) true開啟 ,false不開啟事務(wù),如果開啟記得手動提交  
            //參數(shù)二秀又,表示的是簽收模式单寂,一般使用的有自動簽收和客戶端自己確認(rèn)簽收  
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);  

12、JMS消息生產(chǎn)者
消息生產(chǎn)者由Session創(chuàng)建吐辙,用于往目的地發(fā)送消息宣决。生產(chǎn)者實現(xiàn)MessageProducer接口,我們可以為目的地昏苏、隊列或話題創(chuàng)建生產(chǎn)者尊沸;

1)威沫、隊列(Queue)

            Queue  queue  = session.createQueue("test_queue");  
            //為隊列創(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)這兩種方式只能用在點對點消息模型

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ā)送消息:

//創(chuàng)建消息  
                TextMessage message = session.createTextMessage();  
                message.setText("測試隊列消息"+i);  
                //發(fā)送消息到目的地  
                producer.send(message);  

13、JMS消息消費者
消息消費者由Session創(chuàng)建蜡镶,用于接收目的地發(fā)送的消息雾袱。消費者實現(xiàn)MessageConsumer接口,我們可以為目的地官还、隊列或話題創(chuàng)建消費者芹橡;

1)、隊列(Queue)

          Queue queue = session.createQueue("test_queue"); //隊列(目的地望伦,消費者消費消息的地方)  
          MessageConsumer consumer = session.createConsumer(queue);   //消息消費者  

2)僻族、目的地(Destination)

        //消息目的地  
        Destination destination = session.createQueue("test-queue");  
        //消息消費者  
        MessageConsumer consumer = session.createConsumer(destination);  

3)、話題(Topic)

        //創(chuàng)建話題  
        Topic topic = session.createTopic("myTopic.messages");   
        //為話題創(chuàng)建消費者  
        MessageConsumer consumer = session.createConsumer(topic);   

14屡谐、JMS消息監(jiān)聽器(消息監(jiān)聽這種方式也就是消息的異步接收方式)
JMS消息監(jiān)聽器是消息的默認(rèn)事件處理者,他實現(xiàn)了MessageListener接口蝌数,該接口包含一個onMessage方法愕掏,在該方法中需要定義消息達到后的具體動作。通過調(diào)用setMessageListener方法我們給指定消費者定義了消息監(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

consumer.setMessageListener(new MessageListener(){  
            @Override  
            public void onMessage(Message message){  
                try {  
                TestBean  tbean =(TestBean)((ObjectMessage)message).getObject();  
                System.out.println("tbean: "+tbean);  
                if(null != message) {  
                     System.out.println("收到信息1: "+tbean.getName());  
                }  
                } catch (JMSException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
            }  
        });  

七、JMS消息結(jié)構(gòu)

JMS客戶端使用JMS消息與系統(tǒng)通訊唆貌,JMS消息雖然格式簡單但是非常靈活滑潘, JMS消息由三部分組成:

1、消息頭
JMS消息頭預(yù)定義了若干字段用于客戶端與JMS提供者之間識別和發(fā)送消息锨咙,預(yù)編譯頭如下:

– JMSDestination : 消息發(fā)送的目的地语卤,主要是指Queue和Topic,由session創(chuàng)建而由生產(chǎn)者的send方法設(shè)置.

– JMSDeliveryMode:傳送模式:有兩種即久模式和非持久模式酪刀。一條持久性的消息應(yīng)該被傳輸"一次僅僅一次"粹舵,這就意味著如果JMS提供者出現(xiàn)故障,該消息并不會丟失骂倘,它會在服務(wù)器恢復(fù)之后再次傳遞眼滤。一條非持久的消息最多會傳遞一次,這意味著服務(wù)器出現(xiàn)故障历涝,該消息將永遠(yuǎn)丟失诅需。由session穿件由消息生產(chǎn)者的send方法設(shè)置

– JMSMessageID:唯一識別每個消息的標(biāo)識漾唉,由JMS消息生產(chǎn)者產(chǎn)生。由send方法設(shè)置

– JMSTimestamp:一個JMS Provider在調(diào)用send()方法時自動設(shè)置堰塌,它是消息被發(fā)送和消費者實際接收的時間差赵刑。由客戶端設(shè)置

– JMSCorrelationID:用來連接到另外一個消息,典型的應(yīng)用是在回復(fù)消息中連接到原消息蔫仙。在大多數(shù)情況下料睛,JMSCorrelationID用于將一條消息標(biāo)記為對JMSMessageID標(biāo)示的上一條消息的應(yīng)答,不過摇邦,JMSCorrelationID可以是任何值恤煞,不僅僅是JMSMessageID。由客戶端設(shè)置
– JMSReplyTo:提供本消息回復(fù)消息的目的地址,由客戶端設(shè)置
– JMSRedelivered:如果一個客戶端收到一個設(shè)置了JMSRedelivered屬性的消息施籍,則表示可能客戶端曾經(jīng)在早些時候收到過該消息居扒,但并沒有簽收(acknowledged)。如果該消息被重新傳送丑慎,JMSRedelivered=true 否則 JMSRedelivered=flase 喜喂。由JMS Provider設(shè)置
– JMSType:消息類型的標(biāo)識符,由客戶端設(shè)置
– JMSExpiration:消息過期時間竿裂,等于Destination的send方法中的timeToLive值加上發(fā)送時刻的GMT的時間值玉吁。如果timeToLive值等于零,則JMSExpiration被設(shè)置為零腻异,表示該消息永不過期进副。如果發(fā)送后,在消息過期時間之后消息還沒有被發(fā)送到目的地悔常,則該消息被清除影斑。由send方法設(shè)置
– JMSPriority:消息優(yōu)先級,從0-9十個級別机打,0-4是普通消息矫户,5-9是加急消息。JMS不要求JMS Provider嚴(yán)格按照這十個優(yōu)先級發(fā)送消息残邀,但必須保證加急消息要先于普通消息到達皆辽,默認(rèn)是4級。由send方法設(shè)置
一個消息的消息頭有這些屬性芥挣,我們可以按照需要對這個消息的消息進行設(shè)計膳汪,在將這個消息使用消息生產(chǎn)者的send()方法發(fā)送到消息服務(wù)上。

2九秀、消息屬性

我們可以給消息設(shè)置自定義屬性遗嗽,這些屬性主要是提供給應(yīng)用程序的。對于實現(xiàn)消息過濾功能鼓蜒,消息屬性非常有用痹换,JMS API定義了一些標(biāo)準(zhǔn)屬性征字,JMS服務(wù)提供者可以選擇性的提供部分標(biāo)準(zhǔn)屬性。

3娇豫、消息體

在消息體中匙姜,JMS API定義了五種類型的消息格式,讓我們可以以不同的形式發(fā)送和接受消息冯痢,并提供了對已有消息格式的兼容氮昧。不同的消息類型如下:
Text message : javax.jms.TextMessage,表示一個文本對象浦楣。
Object message : javax.jms.ObjectMessage袖肥,表示一個JAVA對象。
Bytes message : javax.jms.BytesMessage振劳,表示字節(jié)數(shù)據(jù)椎组。
Stream message :javax.jms.StreamMessage,表示java原始值數(shù)據(jù)流历恐。
Map message : javax.jms.MapMessage寸癌,表示鍵值對。

參考文章:http://www.cnblogs.com/chenpi/p/5559349.html#_label6

http://howtodoinjava.com/jms/jms-java-message-service-tutorial/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弱贼,一起剝皮案震驚了整個濱河市蒸苇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吮旅,老刑警劉巖溪烤,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸟辅,居然都是意外死亡,警方通過查閱死者的電腦和手機莺葫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門匪凉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捺檬,你說我怎么就攤上這事再层。” “怎么了堡纬?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵聂受,是天一觀的道長。 經(jīng)常有香客問我烤镐,道長蛋济,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任炮叶,我火速辦了婚禮碗旅,結(jié)果婚禮上渡处,老公的妹妹穿的比我還像新娘。我一直安慰自己祟辟,他們只是感情好医瘫,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旧困,像睡著了一般醇份。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吼具,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天僚纷,我揣著相機與錄音,去河邊找鬼馍悟。 笑死畔濒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锣咒。 我是一名探鬼主播侵状,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毅整!你這毒婦竟也來了趣兄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤悼嫉,失蹤者是張志新(化名)和其女友劉穎艇潭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戏蔑,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蹋凝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了总棵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳍寂。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖情龄,靈堂內(nèi)的尸體忽然破棺而出迄汛,到底是詐尸還是另有隱情,我是刑警寧澤骤视,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布鞍爱,位于F島的核電站,受9級特大地震影響专酗,放射性物質(zhì)發(fā)生泄漏睹逃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一祷肯、第九天 我趴在偏房一處隱蔽的房頂上張望唯卖。 院中可真熱鬧粱玲,春花似錦、人聲如沸拜轨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橄碾。三九已至卵沉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間法牲,已是汗流浹背史汗。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拒垃,地道東北人停撞。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像悼瓮,于是被迫代替她去往敵國和親戈毒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理横堡,服務(wù)發(fā)現(xiàn)埋市,斷路器,智...
    卡卡羅2017閱讀 134,638評論 18 139
  • 什么是Java消息服務(wù) Java消息服務(wù)指的是兩個應(yīng)用程序之間進行異步通信的API命贴,它為標(biāo)準(zhǔn)消息協(xié)議和消息服務(wù)提供...
    雨帶著眼淚滑落閱讀 961評論 1 4
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架道宅,建立于...
    Hsinwong閱讀 22,366評論 1 92
  • 什么是JMS Java消息服務(wù)(Java Message Service,簡稱JMS)是用于訪問企業(yè)消息系統(tǒng)的開發(fā)...
    zach_undefined閱讀 3,691評論 0 1
  • 公司是一個大家庭胸蛛,需要相互維護污茵,只有把大的家照顧好了,自己的小家才會更好葬项,所以工作中同事間需要配合默契泞当,需要遵守公...
    Tracy_zhang閱讀 171評論 0 1