ActiveMQ和spring整合,订阅多个topic并实现监听器监听

本文章适用初学ActiveMQ的同学。

本演示为windows下进行

首先下载ActiveMQ

1.ActiveMQ地址 :http://activemq.apache.org/ 

2.下载完成后解压到本地; 这里我是解压在H:\ruanjian\activeMQ 盘

3.启动本地ActiveMQ服务。

  进入到安装目录双击activemq.bat文件启动,如果启动时窗口一闪而过,可以在cmd窗口,进入按章目录 执行  activemq.bat start 进行启动。

  

看到该窗口说明已启动成功,不要关闭此窗口。

接下来就改开发我们的代码了

首先在工程中添加需要的jar包

<dependency>    
     <groupId>org.apache.activemq</groupId>    
     <artifactId>activemq-core</artifactId>  
     <version>5.7.0</version>  
</dependency>   
<dependency>    
     <groupId>org.apache.activemq</groupId>  
     <artifactId>activemq-pool</artifactId>  
     <version>5.12.1</version>    
</dependency>  
<!-- sping 对消息队列的支持  -->  
<dependency>    
     <groupId>org.springframework</groupId>    
     <artifactId>spring-jms</artifactId>  
     <version>4.1.3.RELEASE</version>  
</dependency>

这里我们创建两个工程,一个是消息生产者,一个是消息消费者

在我们真实的项目中,我们可能会有这样的需求:

1:在商品添加成功后,需要更新商品的索引;

2:会员注册成功后,向用户发送注册成功邮件;

这两个需求我们都可以通过ActiveMQ来实现,我们发布一个主题,让邮件系统和索引系统订阅这个主题,当邮件系统和索引系统监测有消息来时,我们就可以执行我们具体的业务了。

下来我们介绍具体的配置

我们先看消息生产者的配置:

springmvc的配置这里就不做具体的介绍了,我们详细介绍ActiveMQ的配置文件

spring-mq-active.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
        http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd">
 
 
<!-- ActiveMQ 真正产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="admin"></property>
<property name="password" value="admin"></property>
</bean>
 
<!-- 配置spring 管理 connectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="activeMqConnectionFactory" />
<property name="sessionCacheSize" value="100" />
</bean>
 
 
<!-- queue(队列模式),点对点 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="pubSubDomain" value="false" />
</bean>
 
<!-- topic(主题,发布/订阅),一对多 -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="pubSubDomain" value="true" />
<!-- 设置接收超时时间 60秒
<property name="receiveTimeout" value="60000"/> 
-->
<!-- 消息不持久化 -->
<property name="explicitQosEnabled" value="true"></property>
</bean>
</beans>

一、首先我们要配置连接就是ConnectionFactory;

这里的ConnectionFactory分为JMS厂商提供的ConnectionFactory和spring管理服务厂商ConnectionFactory的ConnectionFactory;

比较绕口,就是说spring要管理JSM厂商的ConnectionFactory;

说明:上边代码中的activeMqConnectionFactory就是ActiveMQ提供的ConnectionFactory,connectionFactory就是spring管理ConnectionFactory 的 ConnectionFactory;

Spring提供的ConnectionFactory只是Spring用于管理ConnectionFactory的,真正产生到JMS服务器链接的ConnectionFactory还得是由JMS服务厂商提供,并且需要把它注入到Spring提供的ConnectionFactory中。我们这里使用的是ActiveMQ实现的JMS,所以在我们这里真正的可以产生Connection的就应该是由ActiveMQ提供的ConnectionFactory

spring提供了三中管理器:

1>、SingleConnectionFactory:对于建立JMS服务器链接的请求会一直返回同一个链接,并且会忽略Connection的close方法调用。
2>、CachingConnectionFactory:继承了SingleConnectionFactory,所以它拥有SingleConnectionFactory的所有功能,同时它还新增了缓存功能,
      它可以缓存Session、MessageProducer和MessageConsumer。我们使用CachingConnectionFactory来作为示例。
3>、PooledConnectionFactory:线程池

配置如下

<!-- ActiveMQ 真正产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
	<property name="brokerURL" value="tcp://localhost:61616"/>
	<property name="userName" value="admin"></property>
	<property name="password" value="admin"></property>
</bean>
	
<!-- 配置spring 管理 connectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
	<constructor-arg ref="activeMqConnectionFactory" />
	<property name="sessionCacheSize" value="100" />
</bean>

二、消息发送模板

      连接配置完成后,下来就要配置消息发送模板,既然是发消息我们就要知道是谁发消息,怎么发消息;

      connectionFactory是负责生产消息并发送至JMS服务器;但是具体怎么发,就需要我们的spring提供的JmsTemplate类来实现。所以我们配置消息生产者的核心就是配置JmsTemplate。对于发消息来说,首先是要连接服务器,发什么类型的消息,往哪发。

消息类型:ActiveMQ提供了点对点的队列模式和主题(发布/订阅)模式;

<!-- topic(主题,发布/订阅),一对多 -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="pubSubDomain" value="true" />
<!-- 设置接收超时时间 60秒
<property name="receiveTimeout" value="60000"/> 
-->
<!-- 消息不持久化 -->
<property name="explicitQosEnabled" value="true"></property>
</bean>
</beans>

到此消生产者就已经配置完成了。

三、消费者配置

所谓消费者就是,消息生产者将消息发送到了JMS服务器,那么就得有消费者处理消费这条信息。消息生产者将消息发送至指定的目的地,那么消费者就要开始消费。

那么消费者是怎样知道生产者给自己发消息了呢?所以每个消费者都应有一个对应的消息监听器MessageListenerContainer。而对于监听器来说它要知道去哪监听,监听哪个消息目的地,所以我们配置向监听既要知道 ConnectionFactory(从哪里监听) 和 destination(监听什么),监听到消息后怎么处理,这三个核心的东西。

<!--这个是主题(topic)目的地,一对多的 -->  
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">  
<constructor-arg value="goodsAddTopic,goods2AddTopic" />  
</bean>  
  
<!-- 消息监听类 -->  
<bean id="goodsAddMessageListener" class="com.sxdax.mq.consumer.message.GoodsESMessageLister"/>  
  
<!-- 消息监听器 -->  
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
<property name="connectionFactory" ref="connectionFactory"></property>  
<property name="destination" ref="topicDestination"></property>  
<property name="messageListener" ref="goodsAddMessageListener"></property>
</bean>

connectionFactory这里就不说了,配置同上变的一样。

消费者端ActiveMQ配置文件spring-mq-active.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.1.xsd
        http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd">
 
 
<!-- ActiveMQ 真正产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="admin"></property>
<property name="password" value="admin"></property>
</bean>
 
<!-- 配置spring 管理 connectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="activeMqConnectionFactory" />
<property name="sessionCacheSize" value="100" />
</bean>
 
 
<!--这个是主题(topic)目的地,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="goodsAddTopic,goods2AddTopic" />
</bean>
 
<!-- 消息监听类 -->
<bean id="goodsAddMessageListener" class="com.sxdax.mq.consumer.message.GoodsESMessageLister"/>
 
<!-- 消息监听器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="topicDestination"></property>
<property name="messageListener" ref="goodsAddMessageListener"></property>
</bean>
</beans>

生产者控制层

@Controller
@RequestMapping("test")
public class TestController {
	
	@Autowired
	TopicSender topicSender;
	
	@RequestMapping("send")
	@ResponseBody
	public String sendMessage(){
		System.out.println("开始发送消息");
		topicSender.send("goodsAddTopic", "商品添加成功,开始更新商品索引库");
		return "test success";
	}
	
	@RequestMapping("send2")
	@ResponseBody
	public String sendMessage2(){
		System.out.println("开始发送消息-------------2");
		topicSender.send("goods2AddTopic", "商品添加成功,开始更新商品索引库---------2");
		return "test success";
	}
	
}

生产者实现层:

@Component
public class TopicSender {

	@Autowired
	@Qualifier("jmsTopicTemplate")
	private JmsTemplate jmsTemplate;
	
	/**
	 * 发送一条消息到指定的队列(目标)
	 * @param queueName 队列名称
	 * @param message 消息内容
	 */
	public void send(String topicName,final String message){
		jmsTemplate.send(topicName, new MessageCreator() {
			@Override
			public Message createMessage(Session session) throws JMSException {
				return session.createTextMessage(message);
			}
		});
	}
	
}

注:TopicSender 类必须要扫描,不扫描会报空指针

消费者监听类:

/**
 * 消息监听器,消息的消费者
 * @author back
 */
public class Goods2ESMessageLister implements SessionAwareMessageListener<Message>{


	@Override
	public void onMessage(Message message, Session arg1) throws JMSException {
		try {
            Destination destination = message.getJMSDestination();
            String topic = destination.toString();
            System.out.println("topic====="+topic);
            TextMessage text=(TextMessage) message;
            System.out.println("消息是========"+text.getText());
        }catch (Exception e){

        }
		
	}

}

在运行源代码之前,请先启动您本地的ActiveMQ服务。

猜你喜欢

转载自blog.csdn.net/huxiangen/article/details/81218381
今日推荐