(注:本文內容來自互聯網,大部分內容引用於http://whitesock.javaeye.com/,自己整理以作學習用)
JMS基礎概念
部分一 (引用:《ActiveMq in Action》charpeter1)
JMS Client : An application written using 100% pure Java to send and receive messages.
Non-JMS Client : An appliation in written in a language other than Java to send and receive messages.
JMS Producer : A client application that creates and sends JMS messages.
JMS Consumer : A client application that receives and processes JMS messages.
JMS Provider : The implementation of the JMS interfaces which is ideally written in 100% pure Java.(ex.ActiveMQ)
JMS Message : The most fundamental concept of JMS; sent and recevied by JMS clients.
JMS Domains : The two styles of messaging that include point-to-point and publish/subscribe.
Administered Objects
: Preconfigured JMS objects that contain provider-specific configuration data for use by clients.
These objects are typically accessible by clients via JNDI.
Connection Factory : Clients use a connection factory to create connections to the JMS provider.
Destination : An object to which messages are addressed and sent and from which messages are received.
部分二 (引用:http://whitesock.javaeye.com/blog/164925 )
1 JMS的基本構件
1.1 連接工廠(ConnectionFactory)
連接工廠是客戶用來創建連接的對象,例如ActiveMQ提供的ActiveMQConnectionFactory。
1.2 連接(Connection)
JMS Connection封裝了客戶與JMS提供者之間的一個虛擬的連接。
1.3 會話(Session)
JMS Session是生產和消費消息的一個單線程上下文。會話用於創建消息生產者(producer)、消息消費者(consumer)和消息(message)等。會話提供了一個事務性的上下文,在這個上下文中,一組發送和接收被組合到了一個原子操作中。
1.4 目的地(Destination)
Destination:An object to which messages are addressed and sent and from which messages are received.
目的地是客戶用來指定它生產的消息的目標和它消費的消息的來源的對象。
JMS1.0.2規範中定義了兩種消息傳遞域: Point-to-Point (點對點)消息傳遞域 和 Publich/Subscribe (發佈/訂閱者)消息傳遞域。
點對點消息傳遞域的特點如下:
每個消息只能有一個消費者。
消息的生產者和消費者之間沒有時間上的相關性。無論消費者在生產者發送消息的時候是否處於運行狀態,它都可以提取消息。
發佈/訂閱消息傳遞域的特點如下:
每個消息可以有多個消費者。
生產者和消費者之間有時間上的相關性。訂閱一個主題的消費者只能消費自它訂閱之後發佈的消息。JMS規範允許客戶創建持久訂閱,這在一定程度上放鬆了時間上的相關性要求。持 久訂閱允許消費者消費它在未處於激活狀態時發送的消息。
在點對點消息傳遞域中, 目的地被成爲隊列(queue).
在發佈/訂閱消息傳遞域中,目的地被成爲主題(topic)。
1.5 消息生產者(MessageProducer)
消息生產者是由會話創建的一個對象,用於把消息發送到一個目的地。
1.6 消息消費者(MessageConsumer)
消息消費者是由會話創建的一個對象,它用於接收發送到目的地的消息。
消息的消費可以採用以下兩種方法之一:
同步消費,通過調用消費者的receive方法從目的地中顯式提取消息。receive方法可以一直阻塞到消息到達。
異步消費,客戶可以爲消費者註冊一個消息監聽器,以定義在消息到達時所採取的動作。
1.7 消息
JMS消息由以下三部分組成:
消息頭。每個消息頭字段都有相應的getter和setter方法。
消息屬性。如果需要除消息頭字段以外的值,那麼可以使用消息屬性。
消息體。JMS定義的消息類型有TextMessage、MapMessage、BytesMessage、StreamMessage和ObjectMessage。
2 JMS的可靠性機制
2.1 確認
JMS消息只有在被確認之後,才認爲已經被成功地消費了。
消息的成功消費通常包含三個階段:客戶接收消息、客戶處理消息和消息被確認。
在事務性會話中,當一個事務被提交的時候,確認自動發生。
在非事務性會話中,消息何時被確認取決於創建會話時的應答模式(acknowledgement mode)。該參數有以下三個可選值:
Session.AUTO_ACKNOWLEDGE。當客戶成功的從receive方法返回的時候,或者從MessageListener.onMessage方法成功返回的時候,會話自動確認客戶收到的消息。
Session.CLIENT_ACKNOWLEDGE。客戶通過消息的acknowledge方法確認消息。需要注意的是,在這種模式中,確認是在會話層上進行:確認一個被消費的消息將自動確認所有已被會話消費的消息。例如,如果一個消息消費者消費了10個消息,然後確認第5個消息,那麼所有10個消息都被確認。
Session.DUPS_ACKNOWLEDGE。該選擇只是會話遲鈍第確認消息的提交。如果JMS provider失敗,那麼可能會導致一些重複的消息。如果是重複的消息,那麼JMS provider必須把消息頭的JMSRedelivered字段設置爲true。
2.2 持久性
JMS支持以下兩種消息提交模式:
PERSISTENT,指示JMS provider持久保存消息,以保證消息不會因爲JMS provider的失敗而丟失。
NON_PERSISTENT,不要求JMS provider持久保存消息。
2.3 優先級
可以使用消息優先級來指示JMS provider首先提交緊急的消息。優先級分10個級別,從0(最低)到9(最高)。如果不指定優先級,默認級別是4。需要注意的是,JMS provider並不一定保證按照優先級的順序提交消息。
2.4 消息過期
可以設置消息在一定時間後過期,默認是永不過期。
2.5 臨時目的地
可以通過會話上的createTemporaryQueue方法和createTemporaryTopic方法來創建臨時目的地。它們的存在時間只限於創建它們的連接所保持的時間。只有創建該臨時目的地的連接上的消息消費者才能夠從臨時目的地中提取消息。
2.6 持久訂閱
首先消息生產者必須使用PERSISTENT提交消息。客戶可以通過會話上的createDurableSubscriber方法來創建一個持久訂閱,該方法的第一個參數必須是一個topic。第二個參數是訂閱的名稱。
JMS provider會存儲發佈到持久訂閱對應的topic上的消息。如果最初創建持久訂閱的客戶或者任何其它客戶使用相同的連接工廠和連接的客戶ID、相同的主題和相同的訂閱名再次調用會話上的createDurableSubscriber方法,那麼該持久訂閱就會被激活。JMS provider會象客戶發送客戶處於非激活狀態時所發佈的消息。
持久訂閱在某個時刻只能有一個激活的訂閱者。持久訂閱在創建之後會一直保留,直到應用程序調用會話上的unsubscribe方法。
2.7 本地事務
在一個JMS客戶端,可以使用本地事務來組合消息的發送和接收。JMS Session接口提供了commit和rollback方法。事務提交意味着生產的所有消息被髮送,消費的所有消息被確認;事務回滾意味着生產的所有消息被銷燬,消費的所有消息被恢復並重新提交,除非它們已經過期。
事務性的會話總是牽涉到事務處理中,commit或rollback方法一旦被調用,一個事務就結束了,而另一個事務被開始,關閉事務性會話將回滾其中的事務.
需要注意的是,如果使用請求/回覆機制,即發送一個消息,同時希望在同一個事務中等待接收該消息的回覆,那麼程序將被掛起,因爲知道事務提交,發送操作纔會真正執行。
需要注意的還有一個,消息的生產和消費不能包含在同一個事務中.
3 JMS 規範的變遷
JMS的最新版本的是1.1。它和同1.0.2版本之間最大的差別是,JMS1.1通過統一的消息傳遞域簡化了消息傳遞。這不僅簡化了JMS API,也有利於開發人員靈活選擇消息傳遞域,同時也有助於程序的重用和維護。
以下是不同消息傳遞域的相應接口:
JMS 公共 點對點域 發佈/訂閱域
ConnectionFactory QueueConnectionFactory TopicConnectionFactory
Connection QueueConnection TopicConnection
Destination Queue Topic
Session QueueSession TopicSession
MessageProducer QueueSender TopicPublisher
MessageConsumer QueueReceiver TopicSubscriber
學習參考
ActiveMQ JMS 入門
http://rrsy23.javaeye.com/blog/333246
JMS in action系列
之一: http://whitesock.javaeye.com/blog/164925
之二: http://whitesock.javaeye.com/blog/164933
之三: http://whitesock.javaeye.com/blog/164937
之四: http://whitesock.javaeye.com/blog/164938
之五: http://whitesock.javaeye.com/blog/164942
之六: http://whitesock.javaeye.com/blog/165168
之七: http://whitesock.javaeye.com/blog/165458
Spring JMS
http://whitesock.javaeye.com/blog/306776
ActiveMQ4.1+Spring2.0的Message Driven POJO
http://wiki.springside.org.cn/display/springside/ActiveMQ
http://wiki.springside.org.cn/display/springside/ActiveMQ-part2
其他
http://www.agimatec.de/blog/2008/08/extended-blazeds-and-jms-example/
補充幾個例子
1.在http://rrsy23.javaeye.com/blog/333246 例子中有個同步消息處理的簡單例子,這裏補一個異步消息處理的簡單例子
該例子來自http://my.oschina.net/dxf/blog/405
2. Flex訂閱JMS實時刷新 (來自 http://blog.csdn.net/xieyf_0413/archive/2008/07/19/2677415.aspx)
該例子給出大部分代碼, 這裏作個補充
2.1 SampleBean很簡單,忽略,這裏給出與SampleBean對應的ValueVO.as:
//可以比較下Flex中屬性定義和C#中屬性定義
2.2 ActiveMq使用本地地址,幾個配置文件改了下:
2.2.1 messaging-config.xml
<adapters>
<!-- 這個地方要把註釋去掉,默認是註釋掉的-->
<adapter-definition id="jms" class="flex.messaging.services.messaging.adapters.JMSAdapter"/>
</adapters>
<destination id="message-destination">
<adapter ref="jms"/>
<properties>
<jms>
<destination-type>Topic</destination-type>
<message-type>javax.jms.ObjectMessage</message-type>
<connection-factory>java:comp/env/jms/ConnectionFactory</connection-factory>
<destination-jndi-name>java:comp/env/jms/topic/MyTopic</destination-jndi-name>
<delivery-mode>NON_PERSISTENT</delivery-mode>
<message-priority>DEFAULT_PRIORITY</message-priority>
<acknowledge-mode>AUTO_ACKNOWLEDGE</acknowledge-mode>
<initial-context-environment>
<property>
<name>Context.INITIAL_CONTEXT_FACTORY</name>
<value>org.apache.activemq.jndi.ActiveMQInitialContextFactory</value>
</property>
<property>
<name>Context.PROVIDER_URL</name>
<value>vm://localhost:61616</value>
</property>
</initial-context-environment>
</jms>
</properties>
<channels>
<channel ref="my-amf"/>
</channels>
</destination>
2.2.2 services-config.xml
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://localhost:8080/jmsTopic/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>true</polling-enabled>
<polling-interval-millis>1000</polling-interval-millis>
</properties>
</channel-definition>
2.2.3 context.xml
<Context antiJARLocking="true">
<Resource
name="jms/ConnectionFactory"
auth="Container"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="vm://localhost:61616"
brokerName="LocalActiveMQBroker"
useEmbeddedBroker="true"/>
<Resource name="jms/topic/MyTopic"
auth="Container"
type="org.apache.activemq.command.ActiveMQTopic"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="MY.TEST.FOO"/>
</Context>
主要是tcp uri 改成 vm uri