spring +ActiveMQ 实战 topic selecter指定接收
spring +ActiveMQ 实战 topic selecter指定接收
queue:点对点模式,一个消息只能由一个消费者接受
topic:一对多,发布/订阅模式,需要消费者都在线(可能会导致信息的丢失)
看了网上很多的文件,但大都是不完整的,或不是自己想要的特异性接受功能,特意研究了一下,总结总结
一,下载并安装ActiveMQ
首先我们到apache官网上下载activeMQ(http://activemq.apache.org/download.html),进行解压后运行其bin目录下面的activemq.bat文件启动activeMQ。
二,新建一个maven 项目并导入相关jar包
三,在maven中引入:
<!-- activemq --> <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> </dependencies>
四,spring-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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jms="http://www.springframework.org/schema/jms"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd">
<context:component-scan base-package="com.demo.test1.activemq" />
<mvc:annotation-driven />
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://127.0.0.1:61616"
userName="admin"
password="admin" />
<!-- 配置JMS连接工厂 -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="sessionCacheSize" value="100" />
</bean>
<!-- 定义消息队列(Queue) -->
<bean id="demoQueueDestination" class="org.apache.activemq.command.ActiveMQTopic">
<!-- 设置消息队列的名字 -->
<constructor-arg>
<value>first-queue</value>
</constructor-arg>
</bean>
<jms:listener-container destination-type="topic"
container-type="default" connection-factory="connectionFactory"
acknowledge="auto">
<jms:listener destination="first-queue" selector="con=14" ref="queueMessageListener" />
<jms:listener destination="first-queue" selector="con=15" ref="queueMessageListener2" />
</jms:listener-container>
<!-- 配置JMS模板(Queue),Spring提供的JMS工具类,它发送、接收消息。 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="demoQueueDestination" />
<property name="receiveTimeout" value="10000" />
<!-- true是topic,false是queue,默认是false,此处显示写出false -->
<property name="pubSubDomain" value="true" />
<property name="deliveryMode" value="2"/>
</bean>
<bean id="queueMessageListener" class="com.demo.test1.activemq.filter.QueueMessageListener" />
<bean id="queueMessageListener2" class="com.demo.test1.activemq.filter.QueueMessageListener2" />
</beans>
五,springmvc.xml配置
<?xml version="1.0" encoding="UTF-8"?> <!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 指定Sping组件扫描的基本包路径 --> <context:component-scan base-package="com.demo.test1" > <!-- 这里只扫描Controller,不可重复加载Service --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 启用MVC注解 --> <mvc:annotation-driven /> <!-- JSP视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> <!-- 定义其解析视图的order顺序为1 --> <property name="order" value="1" /> </bean> </beans>
六, web.xml配置
略
七,消息发送接口代码
(1)消息发送接口
import javax.jms.Destination; public interface ProducerService { void sendMessage(Destination destination, final String msg,final int i); }
(2)消息发送接口实现类
import com.demo.test1.activemq.service.ProducerService; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.MessageCreator; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.jms.*; @Service public class ProducerServiceImpl implements ProducerService { @Resource(name="jmsTemplate") private JmsTemplate jmsTemplate; @Override public void sendMessage(Destination destination, final String msg, final int i) { System.out.println(Thread.currentThread().getName()+" 向队列"+destination.toString()+"发送消息--------->"+msg); jmsTemplate.send(destination, new MessageCreator() { public Message createMessage(Session session) throws JMSException { TextMessage textMessage = session.createTextMessage(msg); textMessage.setIntProperty("con",i); return textMessage; } }); } }
八,消息监听代码
(1)queueMessageListener
import javax.jms.*; public class QueueMessageListener implements MessageListener { public void onMessage(Message message) { TextMessage tm = (TextMessage) message; try { System.out.println("MyListenner 1 监听到了文本消息:\t" + tm.getText()); //do something ... } catch (JMSException e) { e.printStackTrace(); } } }
(2)queueMessageListener2
import javax.jms.*; public class QueueMessageListener2 implements MessageListener { @Override public void onMessage(Message message) { TextMessage tm = (TextMessage) message; try { System.out.println("MyListenner 2 监听到了文本消息:\t" + tm.getText()); //do something ... } catch (JMSException e) { e.printStackTrace(); } } }
九,控制层
import com.demo.test1.activemq.service.ConsumerService; import com.demo.test1.activemq.service.ProducerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.jms.Destination; import javax.jms.TextMessage; /** * Created by Administrator on 2017/5/3. */ @Controller public class MessageController { private Logger logger = LoggerFactory.getLogger(MessageController.class); @Resource(name = "demoQueueDestination") private Destination destination; //队列消息生产者 @Resource private ProducerService producer; @RequestMapping(value = "/SendMessage", method = RequestMethod.GET) @ResponseBody public void send(String msg,int i) { logger.info(Thread.currentThread().getName()+"------------开始发送消息"); producer.sendMessage(destination,"消息序号:"+msg,i); logger.info(Thread.currentThread().getName()+"------------发送完毕"); } }
十,启动active和tomcat
启动结果:
总结:
由于我们在监听器的配置中配置了selecter属性,因此MyListenner1,只接受con=14的消息,MyListenner2只接受con=15的消息。
从中可以看到监听的消息队列名称是fist-queue,con值为14的消息,因此值不为14的消息则进入不了该监听消息中。