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

讓我們看看如何使用這些 MessageListenerContainer。 第一步是建立一個可以接收訊息的類別。 為此,必須建立一個實作 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");
	}

}

接下來,你需要配置你的 context 以建立一個 MessageListenerContainer,將訊息路由到此 bean。 你會注意到我在這個範例中使用 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://127.0.0.1:61616" />
	</bean>

</beans>

我現在要跳過它,但顯然你需要啟動一個 MQ,以及一個引導你的 context 的 main 方法。 我已經新增了這個範例的專案歸檔,以便你在需要時查看其餘程式碼。

最後,你只需要運行你的應用程式並查看輸出。

Example Message

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


<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>

我想指出的一件事(從我自己的痛苦經歷中)是確保你不要將 concurrent consumers 與 Topic 一起使用。 請記住,在 JMS topic 中,所有訊息都會傳遞到 topic 上的所有消費者。 這意味著如果你在 topic 上有 concurrent consumers,他們都會收到相同的訊息; 通常是你想要避免的事情。 但是,如果你使用的是佇列,顯然這會以循環方式將每個新訊息分派給消費者。

所以,你明白了。 它不是很花哨,而且可能與你曾經編寫過的程式碼非常相似,但現在你所要做的就是使用它,你不需要維護它。 我還要說這只是冰山一角。 MessageListenerContainer 具有參與交易的能力,使用自訂執行緒池(例如應用程式伺服器提供的執行緒池)與新的 Spring TaskExecutor 抽象,甚至向消費者公開本機 JMS 會話。 儘管如此,這些都是另一個帖子的主題。

獲取 Spring 電子報

與 Spring 電子報保持聯繫

訂閱

領先一步

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

了解更多

獲得支援

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

了解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部