JMS規範及相關實現

原文連接 連接描述html

JMS規範及相關實現
JMS是一種應用於異步消息傳遞的標準API,做爲Java平臺的一部分,JMS能夠容許不一樣應用、不一樣模塊之間實現可靠、異步數據通訊。java

一些概念web

JMS provider數組

An implementation of the JMS interface for a Message Oriented Middleware (MOM). Providers are implemented as either a Java JMS implementation or an adapter to a non-Java MOM.

JMS client服務器

An application or process that produces and/or receives messages.

JMS producer/publishersession

A JMS client that creates and sends messages.

JMS consumer/subscriber多線程

A JMS client that receives messages.

JMS messageapp

An object that contains the data being transferred between JMS clients.

JMS queue異步

A staging area that contains messages that have been sent and are waiting to be read. Note that, contrary to what the name queue suggests, messages don't have to be delivered in the order sent. A JMS queue only guarantees that each message is processed only once.

JMS topicide

A distribution mechanism for publishing messages that are delivered to multiple subscribers.

在JMS中,支持兩種消息模型,點對點(Point-to-point)和發佈-訂閱(Publish and subscribe),這兩種模式分別對應於JMS中的兩種消息目標(Message Destination):隊列及主題。

在點對點模型中,每一個消息都有一個發送者和一個接收者,消息中介(broker)收到發送者的消息,會將消息放入隊列中,而接收者請求並接收隊列中的一條消息後,這條消息就會從隊列中刪除。消息隊列中的每條消息只能投遞給一個接收者,但並不意味着只能使用一個接收者從隊列中取消息,根據業務須要,可使用多個接收者同時從隊列中請求消息,分擔處理壓力。可是須要注意的是,單個接收者收到的消息是按照發送順序的,多個接收者由於多線程的關係,並不能保證收到的消息必定是原序的。

在發佈-訂閱模式中,消息會發送給一個主題,可是與點對點模式不一樣的是消息再也不只被投遞給一個接收者,而是全部此主題的訂閱者都會收到該消息。

JMS消息類型

在JMS1.1規範中,定義了五種消息類型,分別爲:
1.StreamMessage :消息體是 Java 流,寫入和讀出都是順序的
2.MapMessage :消息體包含 key-value 對, key 爲 String , value 爲基本類型,能夠經過迭代器訪問
3.TextMessage :消息體是 String
4.ObjectMessage :消息體是可序列化的 Java 對象
5.BytesMessage :消息體是字節數組
能夠經過 message.clearBody() 來清除消息體;但在消費端,消息體是隻讀的,針對消息的寫操做都會拋出 MessageNotWritableException 異常

JMS消息頭
全部消息的消息頭都具體相同的字段,用於 JMS Client 以及 JMS Provider 對它們進行區別以及進行消息路由
1.JMSDestination
消息發送的目的地(隊列或主題);建立消息時能夠設置 JMSDestination ,可是在發送完成時其值會更新爲發送方所指定的 JMSDestination ,也就是說發送前該字段會被忽略;當消息被消費時,該字段的值與在它被髮送時被設置的值是相同的
如下全部示例均基於ActiveMQ
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立2個目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO2");

// 建立生產者
MessageProducer publisher = session.createProducer(destination);

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 建立消息
TextMessage message = session.createTextMessage("Test Message");
// 設置消息的目的地爲destination2
message.setJMSDestination(destination2);

// 發送消息
publisher.send(message);

System.out.println(message.getJMSDestination());

代碼中,經過 message.setJMSDestination(destination2); 設置了 message 的 JMSDestination 消息頭屬性值,咱們再看看其輸出結果
queue://JMS.DEMO

經過這個例子能夠看出,雖然在發送前設置了消息的目的地,可是發送後消息的目的地被重置了
2.JMSDeliveryMode
指明消息的傳輸模式,有兩種:
DeliveryMode.PERSISTENT :保證消息僅傳一次, JMS Provider 服務中止後消息不會丟失;
DeliveryMode.NON_PERSISTENT :消息最多傳一次,消息會因 JMS Provider 中止後丟失;
同 JMSDestination 同樣,在發送前設置的會被忽略

看下面的例子
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立目的地
Destination destination = session.createQueue("JMS.DEMO");

// 建立生產者
MessageProducer publisher = session.createProducer(destination);

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 發送PERSISTENT消息
publisher.send(session.createTextMessage("PERSISTENT MESSAGE"));

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 發送PERSISTENT消息
publisher.send(session.createTextMessage("NON_PERSISTENT MESSAGE"));

例子中分別發送了一條 PERSISTENT 的消息和一條 NON_PERSISTENT 的消息;當 Active MQ 重啓後,啓動消費端,收到的消息以下
PERSISTENT MESSAGE

該例子說明,在 JMS Provider 重啓後, NON_PERSISTENT 消息丟失了,而 PERSISTENT 消息能正常被消費者消費
3.JMSMessageID
由 JMS Provider 指定的消息的惟一標識符;同上面的字段同樣,在發送前設置的會被忽略,在發送完成時,由 JMS Provider 重置該字段

4.JMSReplyTo
發送端在發送消息時,能夠指定該屬性(爲一個 JMSDestination ),表示指望收到客戶端的響應;是否響應由消費端決定
以下面的例子:
發送端:
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO3");

// 建立生產者
MessageProducer publisher = session.createProducer(destination);

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 建立消息
TextMessage message = session.createTextMessage("Test Message");
message.setJMSReplyTo(destination2);
// 發送消息
publisher.send(message);

接收端(能夠根據狀況決定是否須要回覆)
public void onMessage(Message message) {

try {
    System.out.println("Receive message: " + message);
    if (message.getJMSReplyTo() != null) {
        session.createProducer(message.getJMSReplyTo()).send(session.createTextMessage("This is a reply to"
  • message.getJMSReplyTo()));

    }
    } catch (Exception e) {
        e.printStackTrace();
    }

    }

5.JMSRedelivered
當消費者收到帶有 JMSRedelivered 的消息頭時,代表該消息在過去傳輸過但沒有被確認
JMS Provider 必須對該字段進行設置,當爲 true 時即告知消費者該消息是重傳的,消費者須要自行處理重複的消息

6.JMSExpiration
消息的過時時間,其值爲當前時間加上存活時間(毫秒);當存活時間設置爲 0 時,該字段的值也被設置爲 0 ,表示永不過時;
消費端在通常狀況下都不會接收到過時的消息,但 JMS Provider 並不保證這一點;
下面的例子說明了如何設置消息的過時時間
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立目的地
Destination destination = session.createQueue("JMS.DEMO");

// 建立生產者
MessageProducer publisher = session.createProducer(destination);

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 建立消息
TextMessage message = session.createTextMessage("Test Message");
// 發送消息
publisher.setTimeToLive(5000);
publisher.send(message);

7.JMSPriority
消息的優先級, 0 表明最低優先級, 9 表明最高優先級;通常 0~4 爲普通優先級, 5~9 爲加快優先級
JMS 規範裏並無要求 JMS Provider 嚴格按這個優先級來實現,可是儘量實現加快優先級消息的傳輸在普通消息的前面
同 JMSDestination 同樣,該字段在發送前被忽略,在發送完成時重置

消息屬性

除了前面提到的消息頭之外, JMS 消息還提供了對「屬性值對」的支持,以對消息頭進行擴展;消息屬性主要用於消息選擇器 (message selector 詳見下文 )

1.屬性名
屬性名必須服務消息選擇器的命名規則

2.屬性值
能夠是基本類型及其對象類型以及 Map 、 List 和 String

下面的例子中,消息帶 HashMap 的屬性
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立目的地
Destination destination = session.createQueue("JMS.DEMO");

// 建立生產者
MessageProducer publisher = session.createProducer(destination);

// 設置傳輸模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 建立消息
TextMessage message = session.createTextMessage("Test Message");
// 發送消息
message.setObjectProperty("myProp", new HashMap() {

{
    this.put("key1", "value1");
    this.put("key2", "value2");
}

});
publisher.send(message);

3.清除屬性
JMS 不能清除單個屬性,但能夠經過 Message.clearProperties() 方法清除全部消息屬性

JMS實現(Provider implementations)

要使用JMS,必需要有相應的實現來管理session以及隊列,從Java EE1.4開始,全部的Java EE應用服務器必須包含一個JMS實現。
如下是一些JMS實現:

Apache ActiveMQ
Apache Qpid, using AMQP
BEA Weblogic (part of the Fusion Middleware suite) and Oracle AQ from Oracle
EMS from TIBCO
FFMQ, GNU LGPL licensed
JBoss Messaging and HornetQ from JBoss
JORAM, from the OW2 Consortium
Open Message Queue, from Sun Microsystems
OpenJMS, from The OpenJMS Group
RabbitMQ, using AMQP
Solace JMS from Solace Systems
SonicMQ from Progress Software
StormMQ, using AMQP
SwiftMQ
Tervela
Ultra Messaging from 29 West (acquired by Informatica)
webMethods from Software AG
WebSphere Application Server from IBM, which provides an inbuilt default messaging provider known as the Service Integration Bus (SIBus), or which can connect to WebSphere MQ as a JMS provider [5]
WebSphere MQ (formerly MQSeries) from IBM

Ref from:
1.http://en.wikipedia.org/wiki/Java_Messag...
2.Spring in Action
3.http://goldendoc.iteye.com/blog/1155647

相關文章
相關標籤/搜索