JMS 即 java message service 是爲java提供了一種創建、發送、接收消息的通用方法。可以將複雜的系統進行業務分離,變成靈活的高度解耦合的佈局。同時對我們的日常業務需求開發,提供了非常靈活的業務解決方案。比如繳費還款送積分,送積分的業務邏輯不能影響到繳費還款的業務邏輯,所以最好的,就是繳費/還款邏輯執行完成之後,通過一種方式告訴積分系統,給用戶發送積分,發送積分的結果不要影響到複雜的繳費還款的過程。這種情況下,採用jms進行異步處理,便是一個很好的選擇。
要使用消息的方式來進行系統交互,我們需要一個消息中間平臺,來進行消息的接受轉發,同時處理複雜的消息持久化等問題。本文我們採用activemq來做實驗。這樣的架構下,我們的系統通常會變成如下架構:
消息產生者 -> 消息中心 -> 消息消費者
1、消息的兩種傳播方式
JMS支持兩種消息傳播:PTP 和 PUB/SUB
PTP : 點對點發送。消息的發送方將消息放入管道中,消息的接收方從管道中取出消息並處理。
PUB/SUB : 發佈/訂閱方式。消息的發佈者將自己的主題放入消息中心,同時進行消息投遞,消息訂閱者只獲取自己訂閱的消息。
jms爲了支持上述兩種模式,提供了兩套針對同樣接口的實現,對照關係如下:
ConnectionFacatory:被管理的對象,由客戶端(發佈者/接受者)使用,用來創建一個鏈接。
Connection:提供一個JMS消息的活動鏈接。
Destination:封裝了消息目的地,或者主題類型。
Session:一個用來發送和接受消息的線上上下文。
MessageProducer:由session創建的,用來發送消息的對象。
MessageConsumer:由session創建的用來接受消息的對象。
2、jms消息模型
Jms的消息分爲三部分:消息頭、消息屬性、消息體
消息頭:包含了消息的客戶端和提供者用來路由和識別消息的數據。
消息頭包含的字段:
JMSDestination:包含了消息發往的目的地或者主題信息。
JMSDeliveryMode:消息傳送模式。spring提供額jms模板提供了2種模式(有默認模式):DEFAULT_DELEVERY_MODE 默認模式、DEFAULT_PRIORITY、DEFAULT_TIME_TO_LIVE
JMSMessageID:消息標示,唯一性,每個消息都不同,即便是承載者相同消息體的消息。
JMSTimestamp:發送時間
JMSCorrelationID:與當前消息關聯的其他消息的標示
JMSReplyTo:回覆消息的目的地。帶有這樣屬性的消息通常是發送方希望有一個響應,這個響應是可選的。
JMSRedelivered:帶有該字段的消息通常過去發送過但是沒有被確認,如果要再次發送,提供者必須設置該字段。如果true,則消息接受者必須進行消息重複處理的邏輯。
JMSType:消息類型標示。官方文檔的解釋:
JMSType頭字段包含了由客戶端在發送消息時提供的消息類型標識。一些消息提供者使用消息庫來存儲由應用發送的消息定義。type頭字段可以引用提供者庫中的消息定義。JMS沒有定義一個標準的消息定義庫,也沒有定義這個庫中所包含的各種定義的命名策略。一些消息系統要求每個被創建的應用消息都必須有一個消息類型定義,並且每個消息都指定它的類型。爲了能夠使JMS工作於這些消息系統提供者,無論應用是否使用,JMS客戶端最好賦值JMSType ,這樣可以保證爲需要該頭字段的提供者提供了正確的設置。爲了保證移植性,JMS客戶端應使用安裝時在提供者消息庫中定義的語義值作爲JMSType的值。
JMSExpiration :過期時間。
JMSPriority:優先級。
消息屬性:包括了標準投資段之外的額外添加給消息的可選的字段。比如 應用指定的屬性。
消息體:消息攜帶的內容。
3、消息傳輸編程步驟
1)使用jndi獲取一個ConnectionFacatory對象;
2)使用jndi獲取一個或者多個Destination對象;
3)使用ConnectionFactory創建一個JMS連接;
4)使用連接創建Jms session;
5)使用session和destination創建MessageProducers和MessageConsumers
6)使用Connection進行傳輸消息;
上述是jms的基礎知識,簡單瞭解可以便於下面的應用。jms本身提供了jar可以下載並使用相關配置,結合消息系統來完成消息的發送和接受等操作。但是一種便捷的方式,爲加快開發,可以使用spring提供的jms模板,即JmsTemplate,這個類似於jdbcTemplate。
我們演示PTP和PUB/SUB兩種模式的配置。
先看下基礎公用的類:
我們定義:消息發送者、消息接受者、消息轉換器
第一種,PTP方式的配置:
第二種:PUB/SUB方式的配置
我們配置兩個消息訂閱者,分別訂閱不同的消息,這樣用於判斷是否成功執行了消息的發佈和消息的訂閱
單元測試代碼:
測試結果執行便可。
在這裏,消息系統我們採用的是activemq,試想一個問題,如果消息過多,這個時候發生了宕機,消息是否會丟失?
這裏就涉及到了一個新問題,即消息持久化。
activemq的消息持久化分成兩種:文件和數據庫(支持mysql/oracle)。可以再其配置文件中進行配置,activemq配置文件採用的是spring的方式,所以配置起來非常的方便。
通常下載了activemq後,會有一系列的配置文件demo,可以參照其中的樣例修改即可。
這裏我們使用mysql作爲消息持久化的數據庫服務器。
將mysql的驅動包,拷貝到activemq的lib目錄,配置如下:
conf/activemq.xml
特別注意的是,這裏指定的數據庫名稱,需要事先在mysql中創建好schema。
運行activemq,可以發現自動創建了三張表:
activemq_acks
activemq_lock
activemq_msgs