之前我们一直都是在学习如何使用junit测试ActiveMQ发送/接收消息。本文我们将一起学习下Spring如何与ActiveMQ进行整合。

使用JmsTemplate发送和接收Queue消息

首先,我们要在itheima-activemq工程的pom.xml文件中添加以下两个依赖(由于该工程已经添加了对这两个jar包的依赖,因此我们就不用做这步了)。

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
</dependency>

截图如下:

jmsTemplate 需要手动销毁吗_xml


然后,我们需要在itheima-activemq工程下新建一个关于ActiveMQ的配置文件,如下图所示。

jmsTemplate 需要手动销毁吗_淘淘商城_02


为了方便大家复制,现将applicationContext-activemq.xml配置文件的内容贴出,如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
	
	<!-- 真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供 -->
	<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.81.135:61616"></property>
	</bean>
	<!-- 通用的connectionfacotry,指定真正使用的连接工厂 -->
	<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
		<property name="targetConnectionFactory" ref="targetConnection"></property>
	</bean>
	<!-- 接收和发送消息时使用的类(Spring提供的JmsTemplate模板类)-->
	<bean class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory"></property>
	</bean>
	
	<!-- 这个是队列目的地,点对点的 -->
	<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg name="name" value="item-change-queue"></constructor-arg>
	</bean>

	<!-- 这个是主题目的地,一对多的 -->
	<!-- 
		<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
			<constructor-arg name="name" value="item-change-topic"></constructor-arg>
		</bean> 
	-->
</beans>

这样我们就将Spring与ActiveMQ整合完毕了,下面我们便一起来测试下使用JmsTemplate模板类来发送Queue消息。

jmsTemplate 需要手动销毁吗_java_03


为了方便大家复制,现将以上Producer类的代码给出,如下所示。

package com.itheima.activemq.spring;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class Producer {
	@Test
	public void send() throws Exception{
		// 1.初始化Spring容器
		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-activemq.xml");
		// 2.获取到JmsTemplate对象
		JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
		// 3.获取destination
		Destination destination = (Destination) context.getBean(Destination.class);
		// 4.发送消息
		/*
		 * 第一个参数:指定发送的目的地
		 * 第二个参数:消息的构造器对象,其实就是创建一个消息
		 */
		jmsTemplate.send(destination, new MessageCreator() {
			
			@Override
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage("通过Spring发送的消息123");
			}
		});
		Thread.sleep(100000);
	}
}

运行上面的send方法之后,我们可以在ActiveMQ的后台管理系统页面中看到我们刚才发送的消息,如下图所示。

jmsTemplate 需要手动销毁吗_java_04


发送完Queue消息之后,我们就要来接收Queue消息了。首先,新建一个接收ActiveMQ队列消息的监听器类,该类继承自MessageListener,如下图所示。

jmsTemplate 需要手动销毁吗_java_05


为了方便大家复制,现把以上MyMessageListener类的代码贴出,如下所示。

package com.itheima.activemq.spring;

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

public class MyMessageListener implements MessageListener {

	@Override
	public void onMessage(Message message) {
		// 获取消息
		if(message instanceof TextMessage){
			TextMessage textMessage = (TextMessage) message;
			String text;
			try {
				text = textMessage.getText();
				System.out.println(text);
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}

}

然后,在applicationContext-activemq.xml配置文件配置好我们自定义的监听器类,如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
	
	<!-- 真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供 -->
	<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.81.135:61616"></property>
	</bean>
	<!-- 通用的connectionfacotry,指定真正使用的连接工厂 -->
	<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
		<property name="targetConnectionFactory" ref="targetConnection"></property>
	</bean>
	<!-- 接收和发送消息时使用的类(Spring提供的JmsTemplate模板类)-->
	<bean class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory"></property>
	</bean>
	
	<!-- 这个是队列目的地,点对点的 -->
	<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg name="name" value="item-change-queue"></constructor-arg>
	</bean>

	<!-- 这个是主题目的地,一对多的 -->
	<!-- 
		<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
			<constructor-arg name="name" value="item-change-topic"></constructor-arg>
		</bean> 
	-->
	
	<!-- 消费端,消息的接收端 -->
	<!-- 配置自定义的监听器 -->
	<bean id="myMessageListener" class="com.itheima.activemq.spring.MyMessageListener"></bean>
	<!-- 配置监听容器,其作用是启动线程做监听 -->
	<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory"></property>
		<property name="destination" ref="queueDestination"></property>
		<property name="messageListener" ref="myMessageListener"></property>
	</bean>
	
	<!-- 再增加一个消费者 -->
	<!-- 
		<bean id="myMessageListener2" class="com.itheima.activemq.spring.MyMessageListener"></bean>
		<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
			<property name="connectionFactory" ref="connectionFactory"></property>
			<property name="destination" ref="topicDestination"></property>
			<property name="messageListener" ref="myMessageListener2"></property>
		</bean>
	-->
</beans>

接着,我们便再来运行Producer类中的测试方法,这时在Eclipse控制台我们会看到接收到了两条ActiveMQ队列消息,如下图所示。

jmsTemplate 需要手动销毁吗_淘淘商城_06


第一条是我们上面刚刚发送的ActiveMQ队列消息,由于当时没有消费者,所以这条消息一直留到现在。现在我们有了消费者,自然就消费了那条没有被消费的消息。但是,我们现在又运行了一遍Producer类中的测试方法,导致的结果是又发送了一条队列消息,自然就又会消费一条队列消息了。我们还可以再发送几条ActiveMQ队列消息看看这个控制台是否都能接收到。如下图所示,我们再使用JmsTemplate模板类来发送一条消息,还是可以从控制台中清晰地看到接收到的消息的。

jmsTemplate 需要手动销毁吗_spring_07

使用JmsTemplate发送和接收Topic消息

上面我们已经将Spring与ActiveMQ整合好了,而且测试了一遍使用JmsTemplate模板类来发送和接收Queue消息。本小节就来测试一下使用JmsTemplate模板类来发送和接收Topic消息。

首先,将applicationContext-activemq.xml配置文件的内容修改成下面这个样子。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
	
	<!-- 真正可以产生Connection的ConnectionFactory,由对应的JMS服务厂商提供 -->
	<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.81.135:61616"></property>
	</bean>
	<!-- 通用的connectionfacotry,指定真正使用的连接工厂 -->
	<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
		<property name="targetConnectionFactory" ref="targetConnection"></property>
	</bean>
	<!-- 接收和发送消息时使用的类(Spring提供的JmsTemplate模板类)-->
	<bean class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory"></property>
	</bean>
	
	<!-- 这个是队列目的地,点对点的 -->
	<!-- 
		<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
			<constructor-arg name="name" value="item-change-queue"></constructor-arg>
		</bean> 
	-->

	<!-- 这个是主题目的地,一对多的 -->
	<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
		<constructor-arg name="name" value="item-change-topic"></constructor-arg>
	</bean> 
	
	<!-- 消费端,消息的接收端 -->
	<!-- 配置自定义的监听器 -->
	<bean id="myMessageListener" class="com.itheima.activemq.spring.MyMessageListener"></bean>
	<!-- 配置监听容器,其作用是启动线程做监听 -->
	<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory"></property>
		<property name="destination" ref="topicDestination"></property>
		<property name="messageListener" ref="myMessageListener"></property>
	</bean>
	
	<!-- 再增加一个消费者 -->
	<bean id="myMessageListener2" class="com.itheima.activemq.spring.MyMessageListener"></bean>
	<!-- 配置监听容器,其作用是启动线程做监听 -->
	<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory"></property>
		<property name="destination" ref="topicDestination"></property>
		<property name="messageListener" ref="myMessageListener2"></property>
	</bean>
</beans>

然后,运行一遍Producer类中的测试方法,你便能在Eclipse控制台中看到接收到了两条Topic消息,如下图所示。

jmsTemplate 需要手动销毁吗_jmsTemplate 需要手动销毁吗_08


其中,第一条是模拟消费者1接收到的消息,第二条是模拟消费者2接收到的消息。