之前我们一直都是在学习如何使用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>
截图如下:
然后,我们需要在itheima-activemq工程下新建一个关于ActiveMQ的配置文件,如下图所示。
为了方便大家复制,现将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消息。
为了方便大家复制,现将以上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的后台管理系统页面中看到我们刚才发送的消息,如下图所示。
发送完Queue消息之后,我们就要来接收Queue消息了。首先,新建一个接收ActiveMQ队列消息的监听器类,该类继承自MessageListener,如下图所示。
为了方便大家复制,现把以上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队列消息,如下图所示。
第一条是我们上面刚刚发送的ActiveMQ队列消息,由于当时没有消费者,所以这条消息一直留到现在。现在我们有了消费者,自然就消费了那条没有被消费的消息。但是,我们现在又运行了一遍Producer类中的测试方法,导致的结果是又发送了一条队列消息,自然就又会消费一条队列消息了。
我们还可以再发送几条ActiveMQ队列消息看看这个控制台是否都能接收到。如下图所示,我们再使用JmsTemplate模板类来发送一条消息,还是可以从控制台中清晰地看到接收到的消息的。
使用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消息,如下图所示。
其中,第一条是模拟消费者1接收到的消息,第二条是模拟消费者2接收到的消息。