1,消息监听容器

对于消息监听容器而言,除了要知道监听哪个目的地之外,还需要知道到哪里去监听,也就是说它还需要知道去监听哪个JMS服务器,这是通过在配置MessageConnectionFactory的时候往里面注入一个ConnectionFactory来实现的。所以我们在配置一个MessageListenerContainer的时候有三个属性必须指定,一个是表示从哪里监听的ConnectionFactory;一个是表示监听什么的Destination;一个是接收到消息以后进行消息处理的MessageListener。Spring一共为我们提供了两种类型的MessageListenerContainer,SimpleMessageListenerContainer和DefaultMessageListenerContainer。

SimpleMessageListenerContainer会在一开始的时候就创建一个会话session和消费者Consumer,并且会使用标准的JMS MessageConsumer.setMessageListener()方法注册监听器让JMS提供者调用监听器的回调函数。它不会动态的适应运行时需要和参与外部的事务管理。兼容性方面,它非常接近于独立的JMS规范,但一般不兼容Java EE的JMS限制。

大多数情况下我们还是使用的DefaultMessageListenerContainer,跟SimpleMessageListenerContainer相比,DefaultMessageListenerContainer会动态的适应运行时需要,并且能够参与外部的事务管理。它很好的平衡了对JMS提供者要求低、先进功能如事务参与和兼容Java EE环境。

2.消息监听器

在spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListener、SessionAwareMessageListener和MessageListenerAdapter。下面就分别来介绍一下这几种类型的区别。

MessageListener是最原始的消息监听器,它是JMS规范中定义的一个接口。其中定义了一个用于处理接收到的消息的onMessage方法,该方法只接收一个Message参数。

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;  public class ConsumerMessageListener implements MessageListener {  public void onMessage(Message message) {  //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换,或者直接把onMessage方法的参数改成Message的子类TextMessage  TextMessage textMsg = (TextMessage) message;  System.out.println("接收到一个纯文本消息。");  try {  System.out.println("消息内容是:" + textMsg.getText());  } catch (JMSException e) {  e.printStackTrace();  }  }  }

SessionAwareMessageListener是Spring为我们提供的,它不是标准的JMS MessageListener。MessageListener的设计只是纯粹用来接收消息的,假如我们在使用MessageListener处理接收到的消息时我们需要发送一个消息通知对方我们已经收到这个消息了,那么这个时候我们就需要在代码里面去重新获取一个Connection或Session。SessionAwareMessageListener的设计就是为了方便我们在接收到消息后发送一个回复的消息,它同样为我们提供了一个处理接收到的消息的onMessage方法,但是这个方法可以同时接收两个参数,一个是表示当前接收到的消息Message,另一个就是可以用来发送消息的Session对象。

   public void onMessage(TextMessage message, Session session) throws JMSException {  System.out.println("收到一条消息");  System.out.println("消息内容是:" + message.getText());  MessageProducer producer = session.createProducer(destination);  Message textMessage = session.createTextMessage("ConsumerSessionAwareMessageListener。。。");  producer.send(textMessage);  }  

MessageListenerAdapter类实现了MessageListener接口和SessionAwareMessageListener接口,它的主要作用是将接收到的消息进行类型转换,然后通过反射的形式把它交给一个普通的Java类进行处理。 其另外一个主要的功能是可以自动的发送返回消息

MessageListenerAdapter会把接收到的消息做如下转换:

TextMessage转换为String对象;

BytesMessage转换为byte数组;

MapMessage转换为Map对象;

ObjectMessage转换为对应的Serializable对象。

<bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">  <property name="delegate">  <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>  </property>  <property name="defaultListenerMethod" value="receiveMessage"/>
</bean>
//或者<bean id="messageListenerAdapter"  class="org.springframework.jms.listener.adapter.MessageListenerAdapter">  <constructor-arg>  <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>  </constructor-arg> <property name="defaultListenerMethod" value="receiveMessage"/>  </bean>   

消息回复:

(1),可以通过发送的Message的setJMSReplyTo方法指定该消息对应的回复消息的目的地。 这里我们把我们的生产者发送消息的代码做一下修改,在发送消息之前先指定该消息对应的回复目的地为一个叫responseQueue的队列目的地,具体代码如下所示:

package com.tiantian.springintejms.service.impl;  import javax.jms.Destination;  import javax.jms.JMSException;  import javax.jms.Message;  import javax.jms.Session;  import javax.jms.TextMessage;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.beans.factory.annotation.Qualifier;  import org.springframework.jms.core.JmsTemplate;  import org.springframework.jms.core.MessageCreator;  import org.springframework.stereotype.Component;  import com.tiantian.springintejms.service.ProducerService;  @Component  public class ProducerServiceImpl implements ProducerService {   @Autowired  private JmsTemplate jmsTemplate;  @Autowired  @Qualifier("responseQueue")  private Destination responseDestination;  public void sendMessage(Destination destination, final String message) {  System.out.println("---------------生产者发送消息-----------------");  System.out.println("---------------生产者发了一个消息:" + message);  jmsTemplate.send(destination, new MessageCreator() {  public Message createMessage(Session session) throws JMSException {  TextMessage textMessage = session.createTextMessage(message);  textMessage.setJMSReplyTo(responseDestination);  return textMessage;  }  });  }  }  

xml配置文件:

<!-- 用于测试消息回复的 -->  <bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">  <constructor-arg>  <value>responseQueue</value>  </constructor-arg>  </bean>  <!-- responseQueue对应的监听器 -->  <bean id="responseQueueListener" class="com.tiantian.springintejms.listener.ResponseQueueListener"/>  <!-- responseQueue对应的监听容器 -->  <bean id="responseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">  <property name="connectionFactory" ref="connectionFactory"/>  <property name="destination" ref="responseQueue"/>  <property name="messageListener" ref="responseQueueListener"/>  </bean>  

ResponseQueueListener的定义如下所示:

public class ResponseQueueListener implements MessageListener {  public void onMessage(Message message) {  if (message instanceof TextMessage) {  TextMessage textMessage = (TextMessage) message;  try {  System.out.println("接收到发送到responseQueue的一个文本消息,内容是:" + textMessage.getText());  } catch (JMSException e) {  e.printStackTrace();  }  }  }  }  

生产者发送消息被MessageListenerAdapter处理之后,MessageListenerAdapter把监听器的返回内容封装成一个Message,往原Message通过setJMSReplyTo方法指定的回复目的地发送了一个消息。对于MessageListenerAdapter对应的监听器处理方法返回的是一个null值或者返回类型是void的情况,MessageListenerAdapter是不会自动进行消息的回复的。

(2)通过MessageListenerAdapter的defaultResponseDestination属性来指定。在定义MessageListenerAdapter的时候通过其defaultResponseDestination属性指定其默认的回复目的地是“defaultResponseQueue”,并定义defaultResponseQueue对应的消息监听器和消息监听容器。

<!-- 消息监听适配器 -->
<bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">  <!-- <constructor-arg>  <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>  </constructor-arg> -->  <property name="delegate">  <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>  </property>  <property name="defaultListenerMethod" value="receiveMessage"/>  <property name="defaultResponseDestination" ref="defaultResponseQueue"/>
</bean>  <!-- 消息监听适配器对应的监听容器 -->
<bean id="messageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">  <property name="connectionFactory" ref="connectionFactory"/>  <property name="destination" ref="adapterQueue"/>  <property name="messageListener" ref="messageListenerAdapter"/><!-- 使用MessageListenerAdapter来作为消息监听器 -->
</bean>  !-- 默认的消息回复队列 -->
<bean id="defaultResponseQueue" class="org.apache.activemq.command.ActiveMQQueue">  <constructor-arg>  <value>defaultResponseQueue</value>  </constructor-arg>
</bean>  <!-- defaultResponseQueue对应的监听器 -->
<bean id="defaultResponseQueueListener" class="com.tiantian.springintejms.listener.DefaultResponseQueueListener"/>  <!-- defaultResponseQueue对应的监听容器 -->
<bean id="defaultResponseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">  <property name="connectionFactory" ref="connectionFactory"/>  <property name="destination" ref="defaultResponseQueue"/>  <property name="messageListener" ref="defaultResponseQueueListener"/>
</bean> 

当两种方式都指定了消息的回复目的地的时候使用发送消息的setJMSReplyTo方法指定的目的地将具有较高的优先级,MessageListenerAdapter将只往该方法指定的消息回复目的地发送回复消息。

转载于:https://my.oschina.net/u/2349605/blog/905250

JSM-ActiveMQ相关推荐

  1. Spring-JMS(一)spring整合JSM之activeMQ

    导入依赖 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq- ...

  2. ActiveMQ学习 (一) JSM基本概念

    一.JMS的基本构件: 1.连接工厂:ConnectionFactory是客户用来创建连接的对象 2.连接: Connection封装了客户与JMS提供者之间的一个虚拟连接 3.会话: Session ...

  3. activeMQ Jms Demo

    概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经 ...

  4. JMS ActiveMQ研究文档

    1. 背景 当前,CORBA.DCOM.RMI等RPC中间件技术已广泛应用于各个领域.但是面对规模和复杂度都越来越高的分布式系统,这些技术也显示出其局限性:(1)同步通信:客户发出调用后,必须等待服务 ...

  5. Java消息中间件(activeMQ)

    文章目录 **第一章 消息中间件概述** 1. 消息中间件的好处 2. 什么是消息中间件 3. 什么是JMS(规范) 4. 什么是AMQP(协议) 5. 几个常用消息中间对比 **第二章 初始JMS* ...

  6. ActiveMQ专题

    1. ActiveMQ服务器宕机怎么办?1.这得从ActiveMQ的储存机制说起.在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在 文件中的,它们的最大限制在配置文件的<syst ...

  7. java activeMQ消息的发送与接收

    java activeMQ消息的发送与接收 activemq是我们经常用到的消息队列之一,比如说速度快,对spring的很好的支持,支持多种协议等等,今天我们就来看一下activeMQ消息的发送与接收 ...

  8. Java Message Servicec - ActiveMQ

    上一篇介绍了RabbitMQ的使用,这一篇介绍下JSM的另一个非常好的实现-ActiveMQ,两个框架实现机制基本类似,个人感觉差别并不是很大. 关于ActiveMQ的官方下载链接:https://r ...

  9. springboot整合ActiveMQ(点对点和发布订阅)

    springboot整合ActiveMQ(点对点和发布订阅) ActiveMQ是什么,为什么使用MQ 是基于 Java 中的 JMS 消息服务规范实现的一个消息中间件. 1.系统解耦 采用中间件之后, ...

  10. Java ActiveMQ面试题

    1.如何使用ActiveMQ解决分布式事务? 在互联网应用中,基本都会有用户注册的功能.在注册的同时,我们会做出如下操作: ● 收集用户录入信息,保存到数据库 ● 向用户的手机或邮箱发送验证码 如果是 ...

最新文章

  1. 邁向IT專家成功之路的三十則鐵律 鐵律六:求全求盈之道-佈施
  2. MySQL数据库的账户管理
  3. 【Linux】一步一步学Linux——find命令(47)
  4. php算法学习,php算法学习之动态规划
  5. 关于js函数未定义not defined引发的感想
  6. DRDS 柔性事务漫谈
  7. 凸包算法详解(Graham扫描法)
  8. VS提示error C2011: “timespec”:“struct”类型重定义
  9. Chrome/Edge插件-在线视频画质增强,支持视频加速
  10. CDR制作印章的流程
  11. 项目部署到服务器显示 网页无法访问500 错误的解决办法
  12. KafkaController机制(六):Zookeeper Listener之TopicDeletionManager与DeleteTopicsListener
  13. SDUT 2504 多项式求和
  14. matlab筛选表格数据导出,excel表格里怎么将筛选数据导出-Excel表格在进行筛选,我如何可以导出所有筛选出来......
  15. matlab画渐变色三维柱状图
  16. 【天池学习赛 语义分割】自定义数据集时报错处理
  17. 【面试】面试之哒哒英语
  18. 玩转数据可视化之R语言ggplot2:(三)ggplot2实现将多张图放在一起,包括并排和插图绘制(快速入门)
  19. Glyph 26426 missing from current font. matplotlib显示中文乱码解决
  20. e租宝雇佣黑客攻击网贷之家 帮凶被判二年六个月

热门文章

  1. C语言中itoa和atoi函数的用法
  2. SAR成像系列:【3】合成孔径雷达(SAR)的二维回波信号与简单距离多普勒(RD)算法 (附matlab代码)
  3. Android: How to Capture Screen in Gingerbread(2.3中实现截屏)
  4. html5border设置彩色,css中border颜色不同怎么设置?
  5. 从头搭建一个“微博”有多难
  6. linux显示分区命令,在Linux中查看分区表的4种方法
  7. Educode--机器学习基础模型与算法测试闯关实验
  8. 【强化学习】竞争深度Q网络(Dueling DQN)求解倒立摆问题 + Pytorch代码实战
  9. win10进入不了系统修复方法
  10. grant,revoke,deny 服务器权限控制命令