Spring 2.0 的 JMS 改進

工程 | Ben Hale | 2006 年 4 月 9 日 | ...

隨著 Spring 1.1 的釋出,Spring 社群首次體驗到了 JMS 支援。 此支援包括異常轉換、訊息轉換以及類似於 JdbcTemplate 的模板類。此支援還處理了 JMS 1.0.2 和 1.1 規範之間的域統一。 此支援的核心是 JmsTemplate 類及其 JMS 1.0.2 對應類 JmsTemplate102

與使用原始 JMS API 進行企業訊息傳遞相比,此支援是一項重大改進。 但是,它確實存在一個缺點; JmsTemplate 僅支援使用 JmsTemplate.receive() 方法同步接收訊息。 這種行為對很多人來說都很好用,但絕大多數使用者最終都會推出自己的非同步使用者實現。 簡而言之,他們想要 EJB 2 所謂的 訊息驅動 Bean

使用者無需再這樣做了。 隨著 2.0M1 的釋出以及稍後釋出的最終 2.0 版本,已新增對 JMS 訊息非同步接收的本機支援。 JmsTemplate 仍然用於傳送訊息,但現在它已經加入了 AbstractMessageListenerContainer 的子類,例如 DefaultMessageListenerContainerSimpleMessageListenerContainerServerSessionMessageListener

讓我們來看看如何使用這些 MessageListenerContainers。 第一步是建立一個可以接收訊息的類。 為此,必須建立一個實現 MessageListener 介面的類。


package jmsexample;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ExampleListener implements MessageListener {

	public void onMessage(Message message) {
		if (message instanceof TextMessage) {
			try {
				System.out.println(((TextMessage)message).getText());
			} catch (JMSException e) {
				throw new RuntimeException(e);
			}
		} else {
			throw new IllegalArgumentException(
					"Message must be of type TestMessage");
		}
	}

}

一旦你有了它,你需要一個訊息生產者。 此程式碼與 Spring 2.0 之前的程式碼相同,因此如果你已經有執行此操作的程式碼,則無需進行任何更改。


package jmsexample;

import org.springframework.jms.core.JmsTemplate;

public class ExampleProducer {

	private JmsTemplate jmsTemplate;

	public ExampleProducer(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	public void sendMessage() {
		jmsTemplate.convertAndSend("Example Message");
	}

}

接下來,你需要配置你的上下文以建立一個將訊息路由到此 bean 的 MessageListenerContainer。 你會注意到我在這個例子中使用了 ActiveMQ 實現類。 這恰好是許多 JMS 實現之一,而且恰好是我最熟悉的那個。


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="messageListener" class="jmsexample.ExampleListener" />

	<bean id="messageProducer" class="jmsexample.ExampleProducer">
		<constructor-arg ref="jmsTemplate" />
	</bean>

	<bean id="jmsTemplate"
		class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="destination" />
	</bean>

	<bean id="destination" class="org.activemq.message.ActiveMQQueue">
		<constructor-arg value="jmsExample" />
	</bean>

	<bean id="listenerContainer"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="destination" ref="destination" />
		<property name="messageListener" ref="messageListener" />
	</bean>

	<bean id="connectionFactory"
		class="org.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://:61616" />
	</bean>

</beans>

我暫時跳過它,但顯然你需要啟動一個 MQ,並啟動一個引導你的上下文的 main 方法。 我已經添加了一個 此專案的存檔,這樣你就可以看到其餘的程式碼,如果你需要它。

最後,你只需要執行你的應用程式並檢視輸出。

Example Message

需要注意的一件事是,到目前為止,我們一直在使用單個使用者執行緒進行非同步接收。 可以使用 MessageListenerContainer 的併發使用者屬性將你的使用者進行多執行緒處理(請記住,你仍然需要使它們無狀態或執行緒安全)。


<bean id="listenerContainer"
	class="org.springframework.jms.listener.DefaultMessageListenerContainer">
	<property name="concurrentConsumers" value="5" />
	<property name="connectionFactory" ref="connectionFactory" />
	<property name="destination" ref="destination" />
	<property name="messageListener" ref="messageListener" />
</bean>

我想指出的一件事(來自我自己的痛苦經歷)是確保你不要將併發使用者與 Topic 一起使用。 請記住,在 JMS 主題中,所有訊息都會傳遞到主題上的所有使用者。 這意味著,如果你在一個主題上具有併發使用者,則所有使用者都將收到相同的訊息; 通常是你想要避免的事情。 但是,如果你正在使用佇列,顯然這會將每個新訊息以迴圈方式分發給使用者。

所以,你已經得到了它。 它不是很華麗,並且可能非常類似於你可能在某個時候編寫的東西,但是現在你所要做的就是使用它,你無需維護它。 我還要說這只是冰山一角。 MessageListenerContainers 能夠參與事務,使用自定義執行緒池(例如應用程式伺服器提供的執行緒池)以及新的 Spring TaskExecutor 抽象,甚至向使用者公開本機 JMS 會話。 這些都是另一篇文章的主題。

獲取 Spring 新聞通訊

與 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,以加速你的進步。

瞭解更多

獲得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群中所有即將舉行的活動。

檢視全部