Green Beans:企業訊息傳遞和 Spring 入門
在本文中,我們將介紹訊息傳遞的核心概念,以及 Spring 框架及其姐妹專案提供的豐富訊息傳遞支援。
什麼是訊息傳遞?為了最好地解釋這一點,我將轉述 Gregor Hohpe 和 Bobby Woolf 的開創性著作《企業整合模式》(Addison Wesley, 2004)中提供的示例。當你打電話時,你會嘗試將資訊傳達給另一方。只有當對方在你打電話時能夠接聽,這才會起作用。由於並不總能接到電話,因此我們使用語音郵箱來排隊訊息。呼叫者將訊息留在語音郵箱中,然後被呼叫者可以稍後非同步地檢索訊息(或實際上,許多訊息)。
在這個例子中,語音郵箱位於雙方之間。它儲存訊息,然後在被呼叫者(接收者)檢索時將其傳遞。在企業訊息傳遞領域,情況非常相似:一方將訊息傳送到訊息代理(也稱為訊息導向中介軟體 - MOM),而另一方——當該方能夠——在稍後接收或顯式查詢訊息代理中的任何訊息。
這正是類比停止有用的地方。與語音郵箱相比,訊息代理具有許多選項。訊息代理非常適合提供附加服務,例如路由,並保證訊息傳遞。訊息代理可以針對不同的用例進行最佳化,例如,你可以權衡速度與永續性。訊息代理可能會將訊息持久化到外部儲存以確保永續性,儘管這通常是可以透過配置來切換以提高速度的選項。
在語音郵箱示例中,訊息由一方傳送,然後傳遞給另一方——通訊是*點對點*的。訊息代理支援這一點,以及另一種稱為*釋出/訂閱*的通訊型別,其中訊息會傳遞給多個客戶端。
訊息代理的一個常見用途是解決兩個不同系統之間的整合問題。傳送到訊息代理的資料通常是傳送方和接收方都通用的格式。兩個系統在使用訊息代理時需要就資料合同達成一致。訊息通常包含訊息正文,其中儲存了訊息本身的內容,以及訊息頭,它們是鍵/值對,提供了有關訊息正文的元資料,可用於幫助訊息的消費者處理訊息。訊息頭可以是任何你想要的內容,但它們通常與訊息本身或訊息的處理器相關。
Java Message Service
Java 訊息服務 (JMS) API 規定了與訊息代理互動的客戶端介面。每個訊息代理都提供自己的 API 實現,非常類似於 JDBC 驅動程式對 JDBC API 的作用。這意味著 JMS 客戶端通常應該使用與伺服器相同版本的客戶端。有許多優秀的 JMS 代理實現可供選擇。其中一個原因是訊息傳遞一直是應用程式開發的重要組成部分,並且今天仍然如此。自 1.1 版本以來,JMS 一直是 J2EE(現為 Java EE)規範的一部分。在過去十年的大部分時間裡,JMS 規範都停留在 1.1 版本。
在 JMS 中,客戶端使用 javax.jms.ConnectionFactory 建立 javax.jms.Connection。然後可以使用 Connection 建立 javax.jms.Session。Session 代表客戶端與代理的互動,並允許傳送和接收訊息以及其他不太明顯的。操作。
該介面上最有用的方法與建立 javax.jms.Destination 的訊息生產者和訊息消費者有關。Destination 映射了訊息代理上“地址”的 JMS 概念。它還映射了代理儲存訊息的位置。在 JMS 中,訊息從同一位置傳送、儲存和消費,所有這些都由 javax.jms.Destination 例項表示。
[/caption] Destination 是一個介面,有兩個更具體的子介面 javax.jms.Queue 和 javax.jms.Topic。Queue 代表標準的佇列,這是之前描述的點對點構造。Topic 提供釋出/訂閱訊息傳遞,並將一條訊息傳遞給多個接收者。
要將訊息傳送到 Destination,您必須建立一個 javax.jms.MessageProducer。然後可以使用 MessageProducer 傳送 javax.jms.Message。
JMS 支援兩種不同的接收訊息的機制。第一種方式是使用 javax.jmx.MessageConsumer#receive() 方法來請求訊息,該方法以*同步*方式返回 Destination 中的單個訊息;預設情況下,該方法會阻塞直到收到訊息。而不是使用 MessageConsumer,客戶端可以透過呼叫 javax.jms.Session#setMessageListener(MessageListener) 來安裝 javax.jms.MessageListener。MessageListener 是一個介面,只有一個方法 public void onMessage(javax.jms.Message),每當 Destination 上有可供消費的 javax.jms.Message 時,就會呼叫該方法。MessageListener 提供*非同步*訊息處理:當訊息到達時,它們會被處理。
JMS API 中還有更多內容需要學習,但這些類和概念將在我們討論 Spring 對 JMS 訊息傳遞的支援時對您最有幫助。第一層支援是 org.springframework.jms.core.JmsTemplate,它提供了簡化的方法,將我們剛剛討論的內容減少到一行程式碼。JmsTemplate 需要一個 javax.jms.ConnectionFactory 例項來完成其工作。JmsTemplate 可以為您完成大量工作。例如,要傳送訊息,JmsTemplate 會建立一個 javax.jms.Session,設定一個 javax.jms.MessageConsumer 或 javax.jms.MessageProducer,設定所有事務的機制,併為您提供對當前 javax.jms.Session 的引用,以便您可以建立您選擇的訊息併發送它。考慮到所有錯誤處理和構建邏輯,這很容易節省數十行程式碼。一旦您的訊息已傳送,它就會銷燬或關閉其中大部分物件。這是應用程式伺服器(如 Java EE 伺服器)中的標準做法,因為 ConnectionFactory 例項由伺服器建立、由伺服器管理並進行池化。它們在使用後快取例項。在這些環境中,關閉資源只是將它們返回到池中。因此,JmsTemplate 在標準情況下會做正確的事情,假設 ConnectionFactory 快取或池化例項。
在應用程式伺服器等託管環境中,您通常需要從 JNDI 獲取 javax.jms.ConnectionFactory。您可以使用 Spring 來為您查詢該引用並配置 JmsTemplate。在我們的示例中,我們希望更寬鬆地操作,因此我們將使用獨立的 ActiveMQ 訊息代理。ActiveMQ 是一個流行的、開源訊息代理。要使用它,請下載它,然後在 bin 資料夾中執行適合您作業系統的啟動指令碼。在您的應用程式中,您需要客戶端庫來連線到相應版本的 ActiveMQ。在撰寫本文時,ActiveMQ 的最新版本是 5.4.2。如果您使用 Maven,請將以下依賴項新增到您的 Maven pom 檔案中
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>${activemq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-optional</artifactId>
<version>${activemq.version}</version>
</dependency>
請確保為 ${activemq.version} 建立一個 Maven 屬性,或者手動將字串替換為相應的版本。還有一個 activemq-all 依賴項,但它會拉下許多可能不必要的 jar。對於我們的應用程式,上述兩個依賴項就足夠了。
將 Spring 與 JMS 結合使用
讓我們檢查一個基本 JMS 應用程式的配置。首先,讓我們檢查基本的 Spring XML 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/200…