JMS入門


在不同系統之間交換信息的一大障礙是如何在精確交換和格式化數據方面取得一致。Java Message Service( Java消息服務,簡稱JMS)通過提供一種與J2EE應用程序或傳統系統交互的方法部分的解決了這個問題。


較詳細的介紹在:http://java.sun.com/developer/technicalArticles/Ecommerce/jms/

在此將英文翻譯爲中文,方便中文使用者,翻譯難免出錯,請對照原網址閱讀。


遠程過程調用(RPC)系統,包括Java RMI,是同步調用的。調用者會阻塞直到調用方法執行完畢,這樣在不使用多線程的情況下就無法開發鬆耦合的企業應用程序。也就是說,RPC系統需要客戶端和服務器端同時可用。這樣的緊耦合在某些應用中是無法實現的,而面向消息的中間件(MOM)提供了對這些問題的解決方案。MOM基於異步交互模式,且提供了一個可以在網絡上訪問的抽象化的消息隊列。這裏的消息一般指的是企業級的異步請求或者事件,而不是由人類發出的如電子郵件之類的消息。這些消息包含格式化的描述具體業務操作的數據。

 

Java消息服務(JMS),是由SunMicroSystems公司和其他幾個在JavaCommunity Process下的如JSR 914等公司共同設計出來的第一個企業級的消息API,至今已經獲得廣發的業界支持。JMS的設計目的是爲了更容易地開發能夠進行異步收發業務數據和事件的業務應用程序。它定義了一個通用的企業消息傳遞API,這個API可以很廣泛地支持企業消息傳遞產品。JMS支持點對點(隊列)和發佈-訂閱兩種消息模型。

 

JMS允許Java應用程序使用企業級消息傳遞系統。更重要的是,它提供了一個通用的方式來爲Java應用程序傳遞消息。JMS中間件屬於MOM,作爲中間件,JMS可運行在數據庫、應用程序適配器、事件處理以及業務流程的自動化等層次。MOM已經成爲系統整合公司內部業務方面必不可少的組件。

 

JMS定義了一組用來完成Java應用程序與其他消息實現(messageimplementations)進行通信的接口和語義。一個JMS實現指的就是JMS提供者。JMS最大限度地減少新概念的數目,這樣使得學習JMS能夠更加容易。它同時最大限度地提高了消息應用程序的可移植性。

 

結構

JMS應用一般包含以下部分:

l        JMS提供者:消息傳遞系統,實現了JMS規範。

l        JMS客戶端:收發消息的Java應用程序。

l        消息:在JMS客戶端之間通信的對象。

l        管理的對象:由JMS客戶端管理員創建的預配置的JMS對象。

 

消息傳遞模型

JMS支持兩種不同的消息傳遞模型:

l        點對點(隊列目的地):在這種模式下,消息從一個提供者傳遞給一個消費者。這些消息傳遞到一個目的地(隊列),然後傳送到一個註冊到該隊列的消費者。任何消息提供者都可以向隊列發送消息,該信息被保證傳輸,然後被一個消費者消費。如果沒有註冊的消費者,則這些消息將保存,直到有註冊的消費者來消費。

l        發佈-訂閱(主題目的地):在該模式下,消息會傳遞給任意數量的消費者。消息先傳遞到目的地(主題),然後傳遞給所有訂閱了該主題的消費者。任何消息提供者都可以給一個主題目的地發送消息,而消息也可以被任意數量的訂閱消費者接收。如果沒有註冊消費者,主題目的地不會保存消息,除非它有長期訂閱的但不活動的消費者。長期訂閱不活動的消費者是指那些註冊到主題目的地,且能在消息發送到主題時不活動的消費者。

 

JMS編程模型

一個JMS應用由一組程序定義好的消息和一組交換消息的客戶端組成。客戶端使用JMS API進行交互。一個消息由三部分組成:消息頭,屬性和主體組成。

 

l        消息頭是消息必須包含的信息,消息頭包含了用於路由和標識消息的信息。其中一些字段是由消息提供者在生成和發送下消息時自動設置的,其餘字段則由客戶端進行設置。

l        屬性是可選的,客戶端可以使用它的值來過濾消息。它提供了數據的一些額外信息,比如哪個進程創建了它,它的創建時間等。屬性可以認爲是消息頭的擴展,包含屬性名/值對。使用屬性,客戶端可以精細調整它們的消息選擇標準。

l        主體,也是可選的,包含了要進行交換的實際數據。JMS規定了JMS提供者必須支持的六類消息:

Ø        Message:沒有消息主體的消息。

Ø        StreamMessage:消息主體包含Java原始類型的數據流,按順序寫入與讀取。

Ø        MapMessage:消息主體包含一組名稱/值對,條目的順序沒有定義。

Ø        TextMessage:消息主體包含Java字符串如XML消息。

Ø        ObjectMessage:消息主體包含序列化的Java對象。

Ø        ByteMessage:消息主體包含一個未被解釋的字節流。

 

製造與消費消息

下圖包含製造和消費消息必要步驟。如果客戶端即製造消息,也消費消息,這裏有一些步不能夠重複。

 

製造消息的客戶端

1.      使用JNDI查找一個ConnectionFactory對象,或者直接創建一個ConnectionFactory對象,然後設置它的屬性。這個ConnectionFactory對象是一個QueueConnectionFactory 或者TopicConnectionFactory 的實例。下面的代碼顯示了使用JNDI創建連接工廠對象:

Context ctx = new InitialContext();
ConnectionFactory cf1 = (ConnectionFactory) ctx.lookup("jms/QueueConnectionFactory");
ConnectionFactory cf2 = (ConnectionFactory) ctx.lookup("/jms/TopicConnectionFactory");

       或者直接創建:

ConnectionFactory connFactory = new com.sun.messaging.ConnectionFactory();

 

2.      使用ConnectionFactory對象來創建一個Connection對象:

Connection connection = connFactory.createConnection();

 

3.      使用Connection對象來創建一個或多個Session對象,它提供了一個將發送和接收組織成原子工作單元的事務上下文。

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

CreateSession方法包含兩個參數,第一個參數(這裏爲fasle)表示會話沒有被處理,第二個參數表示會話會自動確認消息的接收。

 

4.      使用JNDI找到目的地,或者直接創建目的地對象:

Destination dest = (Queue) ctx.lookup("jms/SomeQueue");
Queue q = new com.sun.messaging.Queue("world");

 

5.      使用目的地對象和會話對象來創建一個消息製造者,然後使用製造者發送消息:

MessageProducer producer = session.createProducer(SomeQueue OR SomeTopic);
 
producer.send(message);

 

消費消息的客戶端

前四步與上面一致。

5.      使用會話對象和目的地對象來創建一個消息消費者對象:

MessageConsumer consumer = session.createConsumer(SomeQueue or SomeTopic);

在創建消費者對象後,就可以啓動連接對象,來進行消息的收發了:

connection.start();
Message msg = consumer.receive();

 

6.      如果需要進行異步通信,則需要使用一個MessageComsumer對象來實例化一個MessageListener對象,並進行註冊。MessageListener對象作爲一個消息的異步事件處理程序,該接口對象包含一個OnMessage方法,用來實現接收和處理消息。代碼如下:

MessageListener listener = new MyListener();
consumer.setMessageListener(listener);

 

7.      啓動Connection,使用start方法。


一個簡單的實例如下,它來自:http://blog.csdn.net/zhangxs_3/article/details/4034775


import javax.jms.Connection;  
import javax.jms.ConnectionFactory;
import javax.jms.Message;  
import javax.jms.MessageConsumer;  
import javax.jms.MessageProducer;  
import javax.jms.Queue;  
import javax.jms.Session;  
import javax.jms.TextMessage;  
import org.apache.activemq.ActiveMQConnectionFactory;  
import org.apache.activemq.command.ActiveMQQueue;
 
public class MainApp {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");  
        
        Connection connection = factory.createConnection();  
        connection.start();  
         
        Queue queue = new ActiveMQQueue("testQueue");  
         
        final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
        Message message = session.createTextMessage("Hello JMS!");  
         
        MessageProducer producer = session.createProducer(queue);  
        producer.send(message);  
     
        System.out.println("Send Message Completed!");  
         
        MessageConsumer comsumer = session.createConsumer(queue);  
        Message recvMessage = comsumer.receive();  
        System.out.println(((TextMessage)recvMessage).getText());  
        
        connection.stop();
    }

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章