1、什么是JMS
JMS即Java消息服務(Java Message Service)應用程序接口,是一個Java平台中關於面向消息中間件(MOM)的API,用於在兩個應用程序之間,或分布式系統中發送消息,進行異步通信。Java消息服務是一個與具體平台無關的API,絕大多數MOM提供商都對JMS提供支持(百度百科給出的概述)。我們可以簡單的理解:兩個應用程序之間需要進行通信,我們使用一個JMS服務,進行中間的轉發,通過JMS 的使用,我們可以解除兩個程序之間的耦合。
2、JMS的優勢
-
Asynchronous(異步)
JMS is asynchronous by default. So to receive a message, the client is not required to send the request. The message will arrive automatically to the client as they become available.(JMS 原本就是一個異步的消息服務,客戶端獲取消息的時候,不需要主動發送請求,消息會自動發送給可用的客戶端)
-
Reliable(可靠)
JMS provides the facility of assurance that the message will delivered once and only once. You know that duplicate messages create problems. JMS helps you avoiding such problems.(JMS保證消息只會遞送一次。大家都遇到過重復創建消息問題,而JMS能幫你避免該問題。)
3、JMS的消息模型
JMS具有兩種通信模式:
1、Point-to-Point Messaging Domain (點對點)
2、Publish/Subscribe Messaging Domain (發布/訂閱模式)
在JMS API出現之前,大部分產品使用“點對點”和“發布/訂閱”中的任一方式來進行消息通訊。JMS定義了這兩種消息發送模型的規范,它們相互獨立。任何JMS的提供者可以實現其中的一種或兩種模型,這是它們自己的選擇。JMS規范提供了通用接口保證我們基於JMS API編寫的程序適用於任何一種模型。
(1)、Point-to-Point Messaging Domain(點對點通信模型)
a、模式圖:
b、涉及到的概念:
在點對點通信模式中,應用程序由消息隊列,發送方,接收方組成。每個消息都被發送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留着消息,直到他們被消費或超時。
c、特點:
-
-
- 每個消息只要一個消費者
- 發送者和接收者在時間上是沒有時間的約束,也就是說發送者在發送完消息之后,不管接收者有沒有接受消息,都不會影響發送方發送消息到消息隊列中。
- 發送方不管是否在發送消息,接收方都可以從消息隊列中去到消息(The receiver can fetch message whether it is running or not when the sender sends the message)
- 接收方在接收完消息之后,需要向消息隊列應答成功
-
(2)、Publish/Subscribe Messaging Domain(發布/訂閱通信模型)
a、模式圖:
b、涉及到的概念:
在發布/訂閱消息模型中,發布者發布一個消息,該消息通過topic傳遞給所有的客戶端。該模式下,發布者與訂閱者都是匿名的,即發布者與訂閱者都不知道對方是誰。並且可以動態的發布與訂閱Topic。Topic主要用於保存和傳遞消息,且會一直保存消息直到消息被傳遞給客戶端。
c、特點:
-
-
- 一個消息可以傳遞個多個訂閱者(即:一個消息可以有多個接受方)
- 發布者與訂閱者具有時間約束,針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之后,才能消費發布者的消息,而且為了消費消息,訂閱者必須保持運行的狀態。
- 為了緩和這樣嚴格的時間相關性,JMS允許訂閱者創建一個可持久化的訂閱。這樣,即使訂閱者沒有被激活(運行),它也能接收到發布者的消息。
-
4、JMS接收消息
在JMS中,消息的產生和消息是異步的。對於消費來說,JMS的消息者可以通過兩種方式來消費消息。
(1)、同步(Synchronous)
在同步消費信息模式模式中,訂閱者/接收方通過調用 receive()方法來接收消息。在receive()方法中,線程會阻塞直到消息到達或者到指定時間后消息仍未到達。
(2)、異步(Asynchronous)
使用異步方式接收消息的話,消息訂閱者需注冊一個消息監聽者,類似於事件監聽器,只要消息到達,JMS服務提供者會通過調用監聽器的onMessage()遞送消息。
5、JMS編程模型
- 管理對象(Administered objects)-連接工廠(Connection Factories)和目的地(Destination)
- 連接對象(Connections)
- 會話(Sessions)
- 消息生產者(Message Producers)
- 消息消費者(Message Consumers)
- 消息監聽者(Message Listeners)
(1)、Connection Factories
創建Connection對象的工廠,針對兩種不同的jms消息模型,分別有QueueConnectionFactory和TopicConnectionFactory兩種。可以通過JNDI來查找ConnectionFactory對象。客戶端使用一個連接工廠對象連接到JMS服務提供者,它創建了JMS服務提供者和客戶端之間的連接。JMS客戶端(如發送者或接受者)會在JNDI名字空間中搜索並獲取該連接。使用該連接,客戶端能夠與目的地通訊,往隊列或話題發送/接收消息。
QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF"); Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue"); Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");
(2)、Destination
目的地指明消息被發送的目的地以及客戶端接收消息的來源。JMS使用兩種目的地,隊列和話題。如下代碼指定了一個隊列和話題:
創建一個隊列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);
(3)、Connection
Connection表示在客戶端和JMS系統之間建立的鏈接(對TCP/IP socket的包裝)。Connection可以產生一個或多個Session。跟ConnectionFactory一樣,Connection也有兩種類型:QueueConnection和TopicConnection。
連接對象封裝了與JMS提供者之間的虛擬連接,如果我們有一個ConnectionFactory對象,可以使用它來創建一個連接。
Connection connection = connectionFactory.createConnection();
(4)、Session
Session 是我們對消息進行操作的接口,可以通過session創建生產者、消費者、消息等。Session 提供了事務的功能,如果需要使用session發送/接收多個消息時,可以將這些發送/接收動作放到一個事務中。
我們可以在連接創建完成之后創建session:
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
這里面提供了參數兩個參數,第一個參數是是否支持事務,第二個是事務的類型
(5)、Producter
消息生產者由Session創建,用於往目的地發送消息。生產者實現MessageProducer接口,我們可以為目的地、隊列或話題創建生產者;
MessageProducer producer = session.createProducer(dest); MessageProducer producer = session.createProducer(queue); MessageProducer producer = session.createProducer(topic);
(6)、Consumer
消息消費者由Session創建,用於接收被發送到Destination的消息。
MessageConsumer consumer = session.createConsumer(dest); MessageConsumer consumer = session.createConsumer(queue); MessageConsumer consumer = session.createConsumer(topic);
(7)、MessageListener
消息監聽器。如果注冊了消息監聽器,一旦消息到達,將自動調用監聽器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一種MessageListener。