1. 程式人生 > >JMS&MQ,從入門到精通(一)

JMS&MQ,從入門到精通(一)

JMS

JMS即Java訊息服務(Java Message Service)應用程式介面,是一個Java平臺中關於面向訊息中介軟體(MOM)的API,用於在兩個應用程式之間,或分散式系統中傳送訊息,進行非同步通訊。Java訊息服務是一個與具體平臺無關的API,絕大多數MOM提供商(MOM指的是利用高效可靠的訊息傳遞機制進行平臺無關的資料交流,並基於資料通訊來進行分散式系統的整合。)都對JMS提供支援。

JMS是一種與廠商無關的 API,用來訪問訊息收發系統訊息,它類似於JDBC(Java Database Connectivity)。這裡,JDBC 是可以用來訪問許多不同關係資料庫的 API,而 JMS 則提供同樣與廠商無關的訪問方法,以訪問訊息收發服務。許多廠商都支援 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ。 JMS 使您能夠通過訊息收發服務(有時稱為訊息中介程式或路由器)從一個 JMS 客戶機向另一個 JMS客戶機發送訊息。訊息是 JMS 中的一種型別物件,由兩部分組成:報頭和訊息主體。報頭由路由資訊以及有關該訊息的元資料組成。訊息主體則攜帶著應用程式的資料或有效負載。根據有效負載的型別來劃分,可以將訊息分為幾種型別,它們分別攜帶:簡單文字(TextMessage)、可序列化的物件 (ObjectMessage)、屬性集合 (MapMessage)、位元組流 (BytesMessage)、原始值流 (StreamMessage),還有無有效負載的訊息 (Message)。

JMS的一些基本概念

JMS(Java Message Service) 即Java訊息服務。它提供標準的產生、傳送、接收訊息的介面簡化企業應用的開發。它支援兩種訊息通訊模型:點到點(point-to-point)(P2P)模型和釋出/訂閱(Pub/Sub)模型。P2P 模型規定了一個訊息只能有一個接收者;Pub/Sub 模型允許一個訊息可以有多個接收者。
對於點到點模型,訊息生產者產生一個訊息後,把這個訊息傳送到一個Queue(佇列)中,然後訊息接收者再從這個Queue中讀取,一旦這個訊息被一個接收者讀取之後,它就在這個Queue中消失了,所以一個訊息只能被一個接收者消費。
與點到點模型不同,釋出/訂閱模型中,訊息生產者產生一個訊息後,把這個訊息傳送到一個Topic中,這個Topic可以同時有多個接收者在監聽,當一個訊息到達這個Topic之後,所有訊息接收者都會收到這個訊息。

Destination:訊息傳送的目的地,也就是前面說的Queue和Topic。建立好一個訊息之後,只需要把這個訊息傳送到目的地,訊息的傳送者就可以繼續
做自己的事情,而不用等待訊息被處理完成。至於這個訊息什麼時候,會被哪個消費者消費,完全取決於訊息的接受者。
Message:從字面上就可以看出是被髮送的訊息。它有下面幾種型別:
    StreamMessage:Java 資料流訊息,用標準流操作來順序的填充和讀取。
    MapMessage:一個Map型別的訊息;名稱為 string 型別,而值為 Java 的基本型別。
    TextMessage:普通字串訊息,包含一個String。
    ObjectMessage:物件訊息,包含一個可序列化的Java 物件
    BytesMessage:二進位制陣列訊息,包含一個byte[]。
    XMLMessage:  一個XML型別的訊息。
最常用的是TextMessage和ObjectMessage。
Session:與JMS提供者所建立的會話,通過Session我們才可以建立一個Message。
Connection:與JMS提供者建立的一個連線。可以從這個連線建立一個會話,即Session。
JMS提供者的連線,即Conection。
Producer:訊息的生產者,要傳送一個訊息,必須通過這個生產者來發送。
MessageConsumer:與生產者相對應,這是訊息的消費者或接收者,通過它來接收一個訊息。
 前面多次提到JMS提供者,因為JMS給我們提供的只是一系列介面,當我們使用一個JMS的時候,還是需要一個第三方
 的提供者,它的作用就是真正管理這些Connection,Session,Topic和Queue等。  
 那麼可能有人會問: ConnectionFactory和Destination 從哪兒得到?這就和JMS提供者有關了. 如果在一個JavaEE環境中, 可以通過JNDI
 查詢得到, 如果在一個非JavaEE環境中, 那隻能通過JMS提供者提供給我們的介面得到了

一個簡單JMS例項

本例項模擬:1對1的訊息,通知&接受處理,如下圖

這裡寫圖片描述

pom.xml
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-core</artifactId>
        <version>5.7.0</version>
    </dependency>
</dependencies>
test.class
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);

new Thread(() -> {
    try {
        producer.send(message);
    } catch (JMSException e) {
        e.printStackTrace();
    }
}, "theadr-jsm").start();

//下面接受傳送的訊息
System.out.println("Send Message Completed!");
MessageConsumer comsumer = session.createConsumer(queue);

 //接受訊息的方式一
Message recvMessage = comsumer.receive();
System.out.println("received:" + ((TextMessage) recvMessage).getText());

 //接受訊息的方式二(區別一在於,如果有很多訊息,在一中需要while(true){//dosomething },這裡不需要.推薦使用方式二)
 comsumer.setMessageListener(new MessageListener() {
     @Override
     public void onMessage(Message m) {
         TextMessage textMsg = (TextMessage) m;
         try {
             System.out.println("received:" + textMsg.getText());
         } catch (JMSException e) {
             e.printStackTrace();
         }
     }
 });
執行結果如期望一致,下一篇我們介紹"單發/多接受"模式

這裡寫圖片描述