Spring整合JMS-基于activeMQ实现(二)

1、消息监听器

     在Spring整合JMS的应用中我们在定义消息监听器的时候一共能够定义三种类型的消息监听器,各自是MessageListener、SessionAwareMessageListener、MessageListenerAdapter

1.1 MessageListener
     MessageListener是最原始的消息监听器(javax.jms.MessageListener),它是JMS规范中定义的一个接口。定义了一个omMessage方法。仅仅接收一个message參数
     public class ConsumerMessageListener implements MessageListener{
    public void onMessage(Message
message) {
        //这里我们知道生产者发送的就是一个纯文本消息。所以这里能够直接进行强制转换,或者直接把onMessage方法的參数改成Message的子类TextMessage
        TextMessage textMessage = (TextMessage)message;
        System. out.println( "接收到一个纯文本消息" );
        try {
            System. out.println( "消息内容是:" +
textMessage.getText());
        } catch (JMSException
e) {
            e.printStackTrace();
        }
    }
}

1.2 SessionAwareMessageListener
     sessionAwareMessageListener是Spring为我们提供的,它不是标准的JMS消息监听器。MessageListener处理接收到的消息时候假设须要返回消息给对方。此时就须要又一次获取connection和session,SessionAwareMessageListener的设计就是为了方便我们在接收到消息后发送一个回复的消息,onMessage方法中接收两个參数,一个Message。一个发送消息的Session。(看红色新增部分)
     <beans xmlns= "http://www.springframework.org/schema/beans" 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"
       xmlns:context= "http://www.springframework.org/schema/context" xmlns:jms= "http://www.springframework.org/schema/jms"
       xsi:schemaLocation= "
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd
    http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

      <bean id ="connectionFactory" class= "org.springframework.jms.connection.CachingConnectionFactory" >
             <property name ="targetConnectionFactory">
                   <bean class= "org.apache.activemq.ActiveMQConnectionFactory" >
                         <property name ="brokerURL">
                               <value >tcp://localhost:61616 </value >
                         </property >
                   </bean >
             </property >
             <property name ="sessionCacheSize" value= "1" />
      </bean >

      <!-- Spring jmsTemplate queue -->
      <bean id ="jmsTemplate" class= "org.springframework.jms.core.JmsTemplate" >
             <property name ="connectionFactory" ref= "connectionFactory"></property >
             <property name ="defaultDestinationName" value= "subject"></property >
             <property name ="deliveryPersistent" value= "true"></property >
             <property name ="pubSubDomain" value="false"></ property> <!--
false p2p,true topic -->
             <property name ="sessionAcknowledgeMode" value= "1"></property >
             <property name ="explicitQosEnabled" value= "true"></property >
             <property name ="timeToLive" value="604800000"></ property>
      </bean >
      
<!-- 配置Queue,当中value为Queue名称->start -->
      <bean id = "testQueue" class = "org.apache.activemq.command.ActiveMQQueue" >
             <constructor-arg index = "0" value ="${pur.test.add}" />
      </bean >
     
      <bean id = "sessionAwareQueue" class = "org.apache.activemq.command.ActiveMQQueue" >
             <constructor-arg index = "0" value= "queue.liupeng.sessionaware" />
      </bean >
 <!-- 配置Queue,当中value为Queue名称->end -->
     
     
       <!-- 注入AMQ的实现类属性(JmsTemplate和Destination) -->
       <bean id = "amqQueueSender" class = "com.tuniu.scc.purchase.plan.manage.core.amq.AMQQueueSender" >
            <property name = "jmsTemplate" ref="jmsTemplate" ></property >
            <property name = "testQueue" ref="testQueue" ></property >
            <property name = "sessionAwareQueue" ref= "sessionAwareQueue"></property >
       </bean >
      
       <!-- 消息发送必用的发送类 -->
       <bean id = "multiThreadAMQSender" class ="com.tuniu.scc.purchase.plan.manage.core.amq.MultiThreadAMQSender"
             init-method= "init">
             <property name = "jmsTemplate" ref="jmsTemplate" ></property >
             <property name = "multiThreadAMQExecutor" ref= "multiThreadAMQExecutor" ></property >
      </bean >
     
     
<!-- 消息监听器->start -->  
          <bean id = "consumerMessageListener" class= "com.tuniu.scc.purchase.plan.manage.core.amq.ConsumerMessageListener" />
          <!-- 消息监听容器 -->
          <bean id = "jmsContainer" class= "org.springframework.jms.listener.DefaultMessageListenerContainer" >
              <property name = "connectionFactory" ref= "connectionFactory" />  
              <property name = "destination" ref= "testQueue" /> <!--
消费者队列名称,改动 -->
              <property name = "messageListener" ref= "consumerMessageListener" />
          </bean >
         
         <bean id = "consumerSessionAwareMessageListener" class ="com.tuniu.scc.purchase.plan.manage.core.amq.ConsumerSessionAwareMessageListener" >
            <property name ="testQueue" ref="testQueue"/> <!--
接收消息后返回给testQueue队列 --> 
          </bean >
           < bean id= "sessionAwareListenerContainer" class= "org.springframework.jms.listener.DefaultMessageListenerContainer" > 
              <property name ="connectionFactory" ref= "connectionFactory" /> 
              <property name ="destination" ref="sessionAwareQueue" /> 
              <property name ="messageListener" ref= "consumerSessionAwareMessageListener" />  
           </bean > 
 <!-- 消息监听器->end -->  
  
</beans>

     发送消息:
                  @Resource
    private AMQQueueSender amqQueueSender;

    private static final Logger LOG =
LoggerFactory.getLogger(AMQController. class);

    @UvConfig(method
= "testQueue", description = "測试AMQ")
    @RequestMapping(value
= "/testQueue", method = RequestMethod. POST)
    @TSPServiceInfo(name
= "PUR.NM.AMQController.testQueue" ,
description = "測试AMQ")
    public void testQueue(HttpServletRequest
request, HttpServletResponse response) {
        try {
            long beginTime
= System. currentTimeMillis();
            LOG.info( "发送開始");
            //amqQueueSender.sendMessage("test", StaticProperty.TEST_QUEUE);
            amqQueueSender.sendMessage( "test",
StaticProperty.TEST_SESSIONAWARE_QUEUE );
            LOG.info( "发送结束,耗时:" +(System.currentTimeMillis()-beginTime)+ "ms");
        } catch (InterruptedException
e) {
            LOG.error( "測试失败",
e);
        }
    }
     接收消息:
          public class ConsumerSessionAwareMessageListener implements SessionAwareMessageListener<TextMessage>{
    private Destination testQueue; //返回消息目的队列
    @Override
    public void onMessage(TextMessage
message, Session session) throws JMSException {
        System. out.println( "收到一条消息" );
        System. out.println( "消息内容是:" +message.getText());
       
        MessageProducer producer = session.createProducer( testQueue);
        Message txtMessage = session.createTextMessage("consumerSessionAwareMessageListener..." );
        producer.send(txtMessage);
    }
    public Destination
getTestQueue() {
        return testQueue;
    }
    public void setTestQueue(Destination
sessionAwareQueue) {
        this.testQueue =
sessionAwareQueue;
    }
}
     打印结果:
收到一条消息
消息内容是:test
接收到一个纯文本消息
消息内容是:consumerSessionAwareMessageListener...

1.3 MessageListenerAdapter
     MessageListenerAdapter实现了MessageListener接口和SessionAwareMessageListener接口,它的作用主要是将接收到的消息进行类型转换。然后通过反射的形式把它交给一个普通的Java类进行处理。
     MessageListenerAdapter会把接收到的消息做例如以下转换:
          TextMessage转换为String对象
          BytesMessage转换为byte数组
          MapMessage转换为Map对象
          ObjectMessage转换为相应的Serializable对象
     既然前面说到MessageListenerAdapter会把接收到的消息做类型转换再通过反射交给Java类处理,假设真正目标处理器是一个MessageListener或者是一个SessionAwareMessageListener,那么Spring将直接使用接收到的Message对象作为參数调用它们的onMessage方法。而不会利用反射去调用。以下定义的时候为它指定一个目标类
              <!-- 消息监听适配器 -->  
      <bean id ="messageListenerAdapter" class= "org.springframework.jms.listener.adapter.MessageListenerAdapter" > 
               <property name ="delegate"
                  <bean class= "com.tuniu.scc.purchase.plan.manage.core.amq.ConsumerListener" /> 
              </property > 
              <property name ="defaultListenerMethod" value= "receiveMessage"/>
          </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" />  
           </bean >  
     上面说到,目标处理器是一个普通Java类的时候,Spring将进行类型转换之后的对象通过反射去调用真正的方法,那么Spring是怎样知道该调用哪个方法的呢?这是通过MessageListenerAdapter的defaultListenerMethod属性来决定的。当没有指定该属性的时候。会默认调用目标处理器的handleMessage方法

     编写新队列、发送消息同上
     接收消息:
          public class ConsumerListener{
    public void handleMessage(String
message) {  
        System. out.println( "ConsumerListener通过handleMessage接收到一个纯文本消息。消息内容是:" +
message);  
    }  
      
    public void receiveMessage(String
message) {  
        System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息。消息内容是:" +
message);  
    }  
}

     MessageListenerAdapter的另外一个主要功能就是能够自己主动的发送回复的消息
  1. 方法一:
  2. 、public void sendMessage(Destination destination, final String message) {
  3. System.out.println("---------------生产者发送消息-----------------");
  4. System.out.println("---------------生产者发了一个消息:" + message);
  5. jmsTemplate.send(destination, new MessageCreator() {
  6. public Message createMessage(Session session) throws JMSException {
  7. TextMessage textMessage = session.createTextMessage(message);
  8.  textMessage.setJMSReplyTo(responseDestination);  //(省略编写其相应的监听器代码)
  9. return textMessage;
  10. }
  11. });
  12. }

     方法二:
          <!-- 消息监听适配器 -->  
      <bean id ="messageListenerAdapter" class= "org.springframework.jms.listener.adapter.MessageListenerAdapter" > 
               <property name ="delegate"
                  <bean class= "com.tuniu.scc.purchase.plan.manage.core.amq.ConsumerListener" /> 
              </property > 
              <property name ="defaultListenerMethod" value= "receiveMessage"/>
          </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" />
                        <property name="defaultResponseDestination" ref="defaultResponseQueue"/>   
           </bean >


























Spring整合JMS-基于activeMQ实现(二)的更多相关文章

  1. spring整合JMS - 基于ActiveMQ实现

    一. 开篇语 继上一篇apache ActiveMQ之初体验后, 由于近期一直在复习spring的东西, 所以本文就使用spring整合下JMS. 二. 环境准备 1. ActiveMQ5.2.0 ( ...

  2. Spring整合JMS(一)——基于ActiveMQ实现

    1.1     JMS简介 JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到 ...

  3. Spring整合JMS(一)——基于ActiveMQ实现 (转)

    *注:别人那复制来的 1.1     JMS简介 JMS的全称是Java Message Service,即Java消 息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者 ...

  4. 消息中间件ActiveMQ及Spring整合JMS

    一 .消息中间件的基本介绍 1.1 消息中间件 1.1.1 什么是消息中间件 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排 ...

  5. Spring整合JMS(二)——三种消息监听器

    原文地址:http://haohaoxuexi.iteye.com/blog/1893676 1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监 ...

  6. Spring整合JMS(二)——三种消息监听器(转)

    *注:别人那复制来的 1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageList ...

  7. ActiveMQ (三) Spring整合JMS入门

    Spring整合JMS入门 前提:安装好了ActiveMQ  ActiveMQ安装 Demo结构:   生产者项目springjms_producer: pom.xml <?xml versio ...

  8. Spring整合JMS(四)——事务管理

    原文链接:http://haohaoxuexi.iteye.com/blog/1983532 Spring提供了一个JmsTransactionManager用于对JMS ConnectionFact ...

  9. Spring整合JMS——事务管理

    Spring提供了一个JmsTransactionManager用于对JMS ConnectionFactory做事务管理.这将允许JMS应用利用Spring的事务管理特性.JmsTransactio ...

随机推荐

  1. keil uVision4的安装以及KEIL_Lic.exe的注冊

    1.首先毋庸置疑,在网上下载keil uVision4的EXE可运行文件,可能存在两个版本号.51核的单片机(33.3M)和微控制器开发合集(244M),可依据自己的实际须要选择.没有必要都装 2.依 ...

  2. qt宽字符串中文乱码(codec->toUnicode值得学习)

    乱码原因: QT使用的是utf-8 简体中文版的windows操作系统及其应用软件默认都是ANSI/GBK编码.而且这里应该是宽字符串. 多字节ANISGB 宽字符UNICODE 多字节显示标准字符的 ...

  3. Android 特殊符号的转码大全

    项目中要在string.xml 中显示特殊符号,如@号冒号等,直接写肯定不行啦..只能考虑使用ASCII码进行显示: @号 @ :号 : 空格   以下为常见的ASCII十进制交换编码: --> ...

  4. Android代码混淆和项目宣布步骤记录器

    原本放在一起Android项目与发布的文件相混淆.我突然想到,为什么不写博客,分享.有这篇文章的情况下,. Android代码混淆及项目公布步骤记录 一.清理代码中的调试信息,如Log.System. ...

  5. D2010 RTTI + Attribute 简单实现ORM

    还记得David I 今年四月来盛大时,被问及“反射机制能再做得好一点吗?我们想放弃RTTI”,David I 回答“这的确是需要考虑的地方,当然RTTI我们不会放弃的”.(这个白胡子的老哥哥还真很可 ...

  6. 与众不同 windows phone (23) - Device(设备)之硬件状态, 系统状态, 网络状态

    原文:与众不同 windows phone (23) - Device(设备)之硬件状态, 系统状态, 网络状态 [索引页][源码下载] 与众不同 windows phone (23) - Devic ...

  7. JVM查找类文件的顺序(转)

    配置classpath 根据path环境变量的原理,可以定义一个名为classpath环境变量,将要运行的class文件所在目录定义在该变量中. 例:set classpath=c:\ classpa ...

  8. Spring的datasource配置详解

    一句话,Spring对Hibernate的整合,是在applicationContext.xml中配置sessionFactory来实现的,其中sessionFactory中要装配dataSource ...

  9. Threejs 的场景查看 - 几个交互事件库助你方便查看场景

    Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...

  10. HDU 2444 The Accomodation of Students(推断是否是二分图)

    题目链接 题意:n个学生,m对关系,每一对互相认识的能住一个房间.问否把这些学生分成两组,要求每组的学生都互不认识.求最多须要多少个房间. 能否分成两组?也就是说推断是不是二分图,推断二分图的办法,用 ...