前言
前面有一篇博客讲到了spring boot整合jms的使用http://blog.csdn.net/liuchuanhong1/article/details/54603546
但是最近遇到一个需求,需要同时使用jms的队列和topic,于是就有了下面的测试代码:
消费者代码
- @Component // 必须加此注解,该类才会被作为Message Driven POJO使用
- public class Consumer {
- @JmsListener(destination = "mytest.queue")
- public void receiveQueue(TextMessage text) throws Exception {
- System.out.println(Thread.currentThread().getName()+":Consumer收到的报文为:"+text.getText());
- }
-
- @JmsListener(destination="mytest.topic")
- public void receiveTopic(TextMessage text) throws JMSException{
- System.out.println(text.getText());
- }
- }
生产者代码
- @Service("producer")
- public class Producer {
- @Autowired
- private JmsMessagingTemplate jmsTemplate;
-
- public void sendMessage(Destination destination, final String message){
- jmsTemplate.convertAndSend(destination, message);
- }
- }
测试代码
- @RunWith(SpringRunner.class)
- @SpringBootTest
- @EnableAsync //开启对Async的支持,否则异步任务不启作用
- public class SpringbootJmsApplicationTests {
-
- @Autowired
- private Producer producer;
-
- @Test
- public void contextLoads() throws InterruptedException {
- while(true){
- Destination destination = new ActiveMQQueue("mytest.queue");
- Destination topic = new ActiveMQTopic("mytest.topic");
-
- for(int i=0; i<100; i++){
- producer.sendMessage(destination, "myname is chhliu!!!"+i);
- producer.sendMessage(topic, "i'm the king of the world!");
- }
- }
- }
- }
测试结果如下:
- DefaultMessageListenerContainer-6:Consumer收到的报文为:myname is chhliu!!!0
- DefaultMessageListenerContainer-3:Consumer收到的报文为:myname is chhliu!!!1
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!2
- DefaultMessageListenerContainer-4:Consumer收到的报文为:myname is chhliu!!!3
- DefaultMessageListenerContainer-5:Consumer收到的报文为:myname is chhliu!!!4
- DefaultMessageListenerContainer-2:Consumer收到的报文为:myname is chhliu!!!5
- DefaultMessageListenerContainer-6:Consumer收到的报文为:myname is chhliu!!!6
- DefaultMessageListenerContainer-3:Consumer收到的报文为:myname is chhliu!!!7
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!8
- DefaultMessageListenerContainer-4:Consumer收到的报文为:myname is chhliu!!!9
发现一个奇怪的现象,貌似topic没有起效果。于是在配置文件中加了一个配置,配置如下:
- spring.jms.pub-sub-domain=true
然后再跑了一遍上面的测试代码,测试结果如下:
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
- i'm the king of the world!
这次结果是彻底的反了过来,topic生效了,queue却没起作用了。
to be or not to be that's a question!怎么能让两者同时生效了!至少从前面的两次测试结果可以看出,控制哪个生效,是通过设置pubsubdomain来实现的,于是我们解决方案的出发点也在此。
解决方案如下:
- @Configuration
- @EnableJms
- public class JmsConfig {
- @Bean
- public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory) {
- DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
- factory.setPubSubDomain(true);
- factory.setConnectionFactory(connectionFactory);
- return factory;
- }
-
- @Bean
- public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory) {
- DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
- factory.setPubSubDomain(false);
- factory.setConnectionFactory(connectionFactory);
- return factory;
- }
- }
上面的代码的作用是创建了两个JmsListenerContainerFactory,分别是topicListenerFactory和queueListenerFactory,其中topicListenerFactory创建的时候,将pubSubDomain设置成了true,表示该Listener负责处理Topic;queueListenerFactory创建的时候,将pubSubDomain设置成了false,也就是说,jms默认就是queue模式,该Listener主要负责处理Queue。
修改消费者代码:
- @Component // 必须加此注解,该类才会被作为Message Driven POJO使用
- public class Consumer {
- @JmsListener(destination = "mytest.queue" ,containerFactory="queueListenerFactory")// 增加对应处理的监听器工程
- public void receiveQueue(TextMessage text) throws Exception {
- System.out.println(Thread.currentThread().getName()+":Consumer收到的报文为:"+text.getText());
- }
-
- @JmsListener(destination="mytest.topic", containerFactory="topicListenerFactory")// 增加对应处理的监听器工程
- public void receiveTopic(TextMessage text) throws JMSException{
- System.out.println(text.getText());
- }
- }
再跑一下前面的测试,结果如下:
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!1
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!2
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!3
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!4
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!5
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!6
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!7
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!8
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!9
- i'm the king of the world!
- DefaultMessageListenerContainer-1:Consumer收到的报文为:myname is chhliu!!!10
- i'm the king of the world!
我们发现,Queue和Topic都生效了。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。