`
weitao1026
  • 浏览: 1047852 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Spring整合JMS的MessageConverter

阅读更多
消息转换器MessageConverter

      MessageConverter的作用主要有两方面,一方面它可以把我们的非标准化Message对象转换成我们的目标Message对象,这主要是用在发送消息的时候;另一方面它又可以把我们的Message对象转换成对应的目标对象,这主要是用在接收消息的时候。

     下面我们就拿发送一个对象消息来举例,假设我们有这样一个需求:我们平台有一个发送邮件的功能,进行发送的时候我们只是把我们的相关信息封装成一个JMS消息,然后利用JMS进行发送,在对应的消息监听器进行接收到的消息处理时才真正的进行消息发送。

假设我们有这么一个Email对象:


Java代码  收藏代码

    package cn.tzz.jms.activemq.spring.obj; 
     
    import java.io.Serializable; 
     
    public class Email implements Serializable { 
          
        private static final long serialVersionUID = 1L; 
         
        private String receiver; 
        private String title; 
        private String content; 
      
        public Email(String receiver, String title, String content) { 
            this.receiver = receiver; 
            this.title = title; 
            this.content = content; 
        } 
      
        public String getReceiver() { 
            return receiver; 
        } 
      
        public void setReceiver(String receiver) { 
            this.receiver = receiver; 
        } 
      
        public String getTitle() { 
            return title; 
        } 
      
        public void setTitle(String title) { 
            this.title = title; 
        } 
      
        public String getContent() { 
            return content; 
        } 
      
        public void setContent(String content) { 
            this.content = content; 
        } 
     
        @Override 
        public String toString() { 
            return "Email [receiver=" + receiver + ", title=" + title 
                    + ", content=" + content + "]"; 
        } 
         
    } 

 


这个Email对象包含了一个简单的接收者email地址、邮件主题和邮件内容。我们在发送的时候就把这个对象封装成一个ObjectMessage进行发送,使用MessageConverter的时候我们在使用JmsTemplate进行消息发送时只需要调用其对应的convertAndSend方法即可。代码如下所示:
Java代码  收藏代码

    import java.io.Serializable; 
    import javax.jms.Destination; 
     
    public interface EntityProducerService { 
     
        public void sendMessage(Destination destination, final Serializable obj); 
    } 


Java代码  收藏代码

    import java.io.Serializable; 
     
    import javax.jms.Destination; 
     
    import org.springframework.beans.factory.annotation.Autowired; 
    import org.springframework.jms.core.JmsTemplate; 
    import org.springframework.stereotype.Service; 
     
    import cn.tzz.jms.activemq.spring.obj.service.EntityProducerService; 
      
      
    @Service(value="entityProducerService") 
    public class EntityProducerServiceImpl implements EntityProducerService { 
      
        @Autowired 
        private JmsTemplate jmsTemplate; 
         
        public void sendMessage(Destination destination, final Serializable obj) { 
             //未使用MessageConverter的情况   
    //        jmsTemplate.send(destination, new MessageCreator() { 
    //            public Message createMessage(Session session) throws JMSException { 
    //               ObjectMessage objMessage = session.createObjectMessage(obj);   
    //                 return objMessage;   
    //            } 
    //        }); 
          //使用MessageConverter的情况 
            jmsTemplate.convertAndSend(destination, obj);   
        }  
    } 


  这样JmsTemplate就会在其内部调用预定的MessageConverter对我们的消息对象进行转换,然后再进行发送。

       这个时候我们就需要定义我们的MessageConverter了。要定义自己的MessageConverter很简单,只需要实现Spring为我们提供的MessageConverter接口即可。我们先来看一下Spring  MessageConverter接口的定义:


Java代码  收藏代码

    public interface MessageConverter { 
     
        Message toMessage(Object object, Session session); 
        Object fromMessage(Message message); 
    } 

我们可以看到其中一共定义了两个方法fromMessage和toMessage,fromMessage是用来把一个JMS Message转换成对应的Java对象,而toMessage方法是用来把一个Java对象转换成对应的JMS Message。因为我们已经知道上面要发送的对象就是一个Email对象,所以在这里我们就简单地定义一个EmailMessageConverter用来把Email对象和对应的ObjectMessage进行转换,其代码如下:
Java代码  收藏代码

    import java.io.Serializable; 
     
    import javax.jms.JMSException; 
    import javax.jms.Message; 
    import javax.jms.ObjectMessage; 
    import javax.jms.Session; 
     
    import org.springframework.jms.support.converter.MessageConverter; 
     
    public class EmailMessageConverter implements MessageConverter { 
     
        public Message toMessage(Object object, Session session) { 
            ObjectMessage objectMessage = null; 
            try { 
                objectMessage = session.createObjectMessage((Serializable) object); 
            } catch (JMSException e) { 
                e.printStackTrace(); 
            } 
            return objectMessage; 
        } 
     
        public Object fromMessage(Message message) { 
            ObjectMessage objMessage = null; 
            Serializable serializable = null; 
            try { 
                objMessage = (ObjectMessage) message; 
                serializable = objMessage.getObject(); 
            } catch (JMSException e) { 
                e.printStackTrace(); 
            } 
            return serializable; 
        } 
    } 



       这样当我们利用JmsTemplate的convertAndSend方法发送一个Email对象的时候就会把对应的Email对象当做参数调用我们定义好的EmailMessageConverter的toMessage方法。

       定义好我们的EmailMessageConverter之后就需要指定我们用来发送Email对象的JmsTemplate对象的messageConverter为EmailMessageConverter,这里我们在Spring的配置文件中定义JmsTemplate bean的时候就指定:




Java代码  收藏代码

    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --> 
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> 
            <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> 
            <property name="connectionFactory" ref="connectionFactory" /> 
            <!-- 消息转换器 -->   
            <property name="messageConverter" ref="emailMessageConverter"/>   
        </bean> 
     
    <!-- 类型转换器 -->   
        <bean id="emailMessageConverter" class="cn.tzz.jms.activemq.spring.obj.service.impl.EmailMessageConverter"/>   




到此我们的MessageConverter就定义好了,也能够进行使用了.

       上面destination对应的接收处理的MessageListener方法如下所示:



Java代码  收藏代码

    public class ConsumerObjMessageListener implements MessageListener { 
      
        public void onMessage(Message message) { 
             
            if (message instanceof ObjectMessage) { 
                ObjectMessage objMessage = (ObjectMessage) message; 
                try { 
                    Object obj = objMessage.getObject(); 
                    Email email = (Email) obj; 
                    System.out.println("接收到一个ObjectMessage,包含Email对象。"); 
                    System.out.println(email); 
                } catch (JMSException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
      
    } 



       之前说了MessageConverter有两方面的功能,除了把Java对象转换成对应的Jms Message之外还可以把Jms Message转换成对应的Java对象。我们看上面的消息监听器在接收消息的时候接收到的就是一个Jms Message,如果我们要利用MessageConverter来把它转换成对应的Java对象的话,只能是我们往里面注入一个对应的MessageConverter,然后在里面手动的调用,如:



Java代码  收藏代码

    package cn.tzz.jms.activemq.spring.listener; 
     
    import javax.jms.Message; 
    import javax.jms.MessageListener; 
    import javax.jms.ObjectMessage; 
     
    import org.springframework.jms.support.converter.MessageConverter; 
     
    import cn.tzz.jms.activemq.spring.obj.Email; 
     
    public class ConsumerObjMessageListener implements MessageListener { 
     
        private MessageConverter emailMessageConverter; 
     
        public void onMessage(Message message) { 
            if (message instanceof ObjectMessage) { 
                ObjectMessage objMessage = (ObjectMessage) message; 
                try { 
    //              Object obj = objMessage.getObject(); 
    //              Email email = (Email) obj; 
                    Email email = (Email) emailMessageConverter.fromMessage(objMessage);  
                    System.out.println("ConsumerObjMessageListener"); 
                    System.out.println("接收到一个ObjectMessage,包含Email对象。"); 
                    System.out.println(email); 
                } catch (Exception e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
     
        public MessageConverter getEmailMessageConverter() { 
            return emailMessageConverter; 
        } 
     
        public void setEmailMessageConverter(MessageConverter emailMessageConverter) { 
            this.emailMessageConverter = emailMessageConverter; 
        } 
    } 



       当我们使用MessageListenerAdapter来作为消息监听器的时候,我们可以为它指定一个对应的MessageConverter,这样Spring在处理接收到的消息的时候就会自动地利用我们指定的MessageConverter对它进行转换,然后把转换后的Java对象作为参数调用指定的消息处理方法。这里我们再把前面讲解MessageListenerAdapter时定义的MessageListenerAdapter拿来做一个测试,我们指定它的MessageConverter为我们定义好的EmailMessageConverter。



Xml代码  收藏代码

     <context:annotation-config /> 
        <context:component-scan base-package="cn.tzz.jms.activemq.spring.obj" /> 
             
        <!-- ActiveMQ --> 
        <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供--> 
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> 
            <property name="brokerURL" value="tcp://localhost:61616"/> 
        </bean> 
        <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"> 
            <property name="connectionFactory" ref="targetConnectionFactory"/> 
            <property name="maxConnections" value="10"/> 
        </bean> 
        <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> 
            <property name="targetConnectionFactory" ref="pooledConnectionFactory"/> 
        </bean> 
         
     
        <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --> 
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> 
            <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> 
            <property name="connectionFactory" ref="connectionFactory" /> 
            <!-- 消息转换器 -->   
            <property name="messageConverter" ref="emailMessageConverter"/>   
        </bean> 
        <!--消息队列的目的地,点对点的 --> 
        <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue"> 
            <constructor-arg> 
                <value>queue</value> 
            </constructor-arg> 
        </bean> 
        <!--这个是主题目的地,一对多的 --> 
        <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"> 
            <constructor-arg value="topic" /> 
        </bean> 
         
        <bean id="adapterQueue" class="org.apache.activemq.command.ActiveMQQueue">   
            <constructor-arg>   
                <value>adapterQueue</value>   
            </constructor-arg>   
        </bean>   
        
        <!-- 类型转换器 -->   
        <bean id="emailMessageConverter" class="cn.tzz.jms.activemq.spring.obj.service.impl.EmailMessageConverter"/>   
         
        <!-- 自定义消息监听 --> 
        <bean id="consumerObjMessageListener" class="cn.tzz.jms.activemq.spring.listener.ConsumerObjMessageListener"> 
            <property name="emailMessageConverter" ref="emailMessageConverter"/>   
        </bean> 
         
        <!-- MessageListenerAdapter 消息监听 --> 
        <bean id="objMessageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> 
            <property name="delegate"> 
                <bean class="cn.tzz.jms.activemq.spring.listener.ConsumerListener"/> 
            </property> 
            <property name="defaultListenerMethod" value="receiveMessage"/> 
            <property name="messageConverter" ref="emailMessageConverter"/> 
        </bean> 
         
        <!-- 消息监听适配器对应的监听容器 --> 
        <bean id="objMessageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 
            <property name="connectionFactory" ref="connectionFactory"/> 
            <property name="destination" ref="adapterQueue"/> 
    <!--         <property name="messageListener" ref="objMessageListenerAdapter"/> --> 
            <property name="messageListener" ref="consumerObjMessageListener"/> 
        </bean> 



       然后在我们的真正用于处理接收到的消息的ConsumerListener中添加一个receiveMessage方法,添加后其代码如下所示:


Java代码  收藏代码

    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); 
    //    } 
    //    public String receiveMessage(String message) { 
    //      System.out.println("ConsumerListener通过receiveMessage接收到消息:" + message); 
    //      return "这是ConsumerListener对象的receiveMessage方法的返回值。";   
    //    } 
         
        public void receiveMessage(Email email) {   
            System.out.println("接收到一个包含Email的ObjectMessage。");   
            System.out.println(email);   
        }   
    } 



       然后我们定义如下测试代码:



Java代码  收藏代码

    @RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration("/applicationContext2.xml") 
    public class EntiryProducerConsumerTest { 
     
        @Resource(name="entityProducerService") 
        private EntityProducerService entityProducerService; 
        @Autowired   
        @Qualifier("adapterQueue")   
        private Destination adapterQueue;   
           
        @Test   
        public void testObjectMessage() { 
            Email email = new Email("test@qq.com", "测试", "HellWorld"); 
            entityProducerService.sendMessage(adapterQueue, email); 
        } 
    } 



       因为我们给MessageListenerAdapter指定了一个MessageConverter,而且是一个EmailMessageConverter,所以当MessageListenerAdapter接收到一个消息后,它会调用我们指定的MessageConverter的fromMessage方法把它转换成一个Java对象,根据定义这里会转换成一个Email对象,然后会把这个Email对象作为参数调用我们通过defaultListenerMethod属性指定的默认处理器方法,根据定义这里就是receiveMessage方法,但是我们可以看到在ConsumerListener中我们一共定义了两个receiveMessage方法,因为是通过转换后的Email对象作为参数进行方法调用的,所以这里调用的就应该是参数类型为Email的receiveMessage方法了。

上述测试代码运行后会输出如下结果:

接收到一个ObjectMessage,包含Email对象。

Email [receiver=test@qq.com, title=测试, content=HellWorld]


        说到这里可能有读者就会有疑问了,说我们在之前讲解MessageListenerAdapter的时候不是没有指定对应的MessageConverter,然后发送了一个TextMessage,结果Spring还是把它转换成一个String对象,调用了ConsumerListener参数类型为String的receiveMessage方法吗?那你这个MessageConverter在MessageListenerAdapter进行消息接收的时候也没什么用啊。

       其实还是有用的,在我们使用MessageListenerAdapter时,在对其进行初始化也就是调用其构造方法时,它会默认new一个Spring已经为我们实现了的MessageConverter——SimpleMessageConverter作为其默认的MessageConverter,这也就是为什么我们在使用MessageListenerAdapter的时候不需要指定MessageConverter但是消息还是会转换成对应的Java对象的原因。所以默认情况下我们使用MessageListenerAdapter时其对应的MessageListener的处理器方法参数类型必须是一个普通Java对象,而不能是对应的Jms Message对象。

       那如果我们在处理Jms Message的时候想使用MessageListenerAdapter,然后又希望处理最原始的Message,而不是经过MessageConverter进行转换后的Message该怎么办呢?这个时候我们只需要在定义MessageListenerAdapter的时候指定其MessageConverter为空就可以了。



Xml代码  收藏代码

    <!-- 消息监听适配器 --> 
    <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"/> 
        <property name="messageConverter"> 
            <null/> 
        </property> 
    </bean> 



       那么这个时候我们的真实MessageListener的处理器方法参数类型就应该是Jms Message或对应的Jms Message子类型了,不然就会调用不到对应的处理方法了。这里因为我们发送的是一个ObjectMessage,所以这里就添加一个对应的参数类型为ObjectMessage的receiveMessage方法了。



Java代码  收藏代码

    public void receiveMessage(ObjectMessage message) throws JMSException { 
        System.out.println(message.getObject()); 
    } 



       刚刚讲到Spring已经为我们实现了一个简单的MessageConverter,即org.springframework.jms.support.converter.SimpleMessageConverter,其实Spring在初始化JmsTemplate的时候也指定了其对应的MessageConverter为一个SimpleMessageConverter,所以如果我们平常没有什么特殊要求的时候可以直接使用JmsTemplate的convertAndSend系列方法进行消息发送,而不必繁琐的在调用send方法时自己new一个MessageCreator进行相应Message的创建。
分享到:
评论

相关推荐

    Spring整合JMS(三)——MessageConverter介绍

    总结,Spring整合JMS中的MessageConverter是实现数据在Java对象和JMS消息间转换的关键。正确地选择和配置MessageConverter,能有效提高系统通信的效率和灵活性,同时降低开发复杂度。在实际应用中,根据业务需求选择...

    spring整合jms+activemq

    综上所述,Spring整合JMS和ActivemQ提供了一套完整的解决方案,帮助开发者轻松地在应用中实现消息的发送和接收。通过这种方式,可以构建出高可用、松耦合、可扩展的分布式系统,提高系统的稳定性和响应速度。在实际...

    Spring整合JMS

    当我们谈论"Spring整合JMS"时,意味着我们要将Spring框架与Java消息服务(Java Message Service)进行集成,以便利用JMS的异步通信能力来处理应用程序中的消息传递。 **JMS简介** JMS是一种标准API,用于在分布式...

    spring整合JMS实现同步收发消息(基于ActiveMQ的实现)

    Spring 整合 JMS 实现同步收发消息(基于 ActiveMQ 的实现) Spring 整合 JMS 实现同步收发消息是指在 Spring 框架下使用 JMS(Java Message Service)协议来实现消息的同步收发。JMS 是一个基于 Java 的消息服务 ...

    jms-spring.zip

    - Spring支持与JMS的事务整合,可以确保消息的可靠传递,即使在系统故障时也能保证数据一致性。 7. **异常处理**: - 消息监听器可以抛出异常来拒绝消息,Spring提供了一套完整的异常处理机制。 8. **消息选择器...

    Spring+weblogic接收JMS消息

    标题"Spring+weblogic接收JMS消息"涉及到的核心知识点是Spring框架与WebLogic Server之间的整合,以及如何利用Spring来处理JMS消息。下面将详细讲解这两个方面的内容。 1. **Spring对JMS的支持**: - Spring通过`...

    Spring整合activemq

    首先,我们要理解Spring整合ActiveMQ的核心概念。在Spring框架中,我们可以通过使用Spring的JMS模块来配置ActiveMQ。这个过程涉及到以下几个关键点: 1. **JMS配置**:在Spring的配置文件中,我们需要定义一个`...

    JMS整合Spirng

    将JMS与Spring整合,可以充分利用Spring的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,实现消息驱动的解耦和事务管理。 在Spring框架中,JMS的整合主要通过...

    spring整合activeMQ

    本文将围绕"Spring整合ActiveMQ"这一主题,深入讲解如何在Spring框架中实现ActiveMQ的集成。 1. **Spring与ActiveMQ的整合基础** - Spring框架提供了一套完整的消息编程模型,包括Message、MessageListener、...

    JMS入门Demo

    在Spring整合JMS的应用中,如果我们要进行本地的事务管理的话非常简单,只需要在定义对应的消息监听容器时指定其sessionTransacted属性为true,如: &lt;bean id="jmsContainer" class="org.springframework.jms....

    sample-spring-boot-war-jms:使用JPA和Spring-Boot的示例Spring JMS

    **Spring Boot与JMS整合详解** 在现代Java开发中,Spring Boot因其简洁的配置和强大的功能,已经成为构建微服务和企业级应用的首选框架。同时,Java消息服务(JMS)作为异步通信的重要工具,常用于解耦系统组件、...

    多个spring 和ActiveMQ结合的项目

    在项目中整合Spring和ActiveMQ,我们需要做以下几步: 1. **配置ActiveMQ**:首先,需要在项目中引入ActiveMQ的相关依赖。这通常通过在`pom.xml`文件中添加Maven依赖来完成。同时,配置ActiveMQ服务器的连接信息,...

    springboot整合activemq案例

    在本文中,我们将深入探讨如何将Spring Boot与ActiveMQ整合,构建一个实用的消息传递系统。首先,我们需要了解Spring Boot和ActiveMQ的基本概念。 Spring Boot是一个快速开发框架,它简化了基于Spring的应用程序...

    SpringBoot快速玩转ActiveMQ消息队列

    这通常涉及到创建一个实现`MessageConverter`接口的类,并在Spring配置中声明使用。 **四、高级特性** 除了基本的发送和接收消息外,ActiveMQ还提供了一些高级特性,例如: - **持久化**:可以设置消息的持久性,...

Global site tag (gtag.js) - Google Analytics