`
xiao_nan_ren
  • 浏览: 2458 次
社区版块
存档分类
最新评论

spring jms messageConverter

阅读更多
Spring整合JMS(三)——MessageConverter介绍

    博客分类: Spring

SpringjmsintegratemessageConverter
1.4     消息转换器MessageConverter

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

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

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


Java代码  收藏代码

    public class Email implements Serializable { 
      
        private static final long serialVersionUID = -658250125732806493L; 
      
        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() { 
            StringBuilder builder = new StringBuilder(); 
            builder.append("Email [receiver=").append(receiver).append(", title=") 
                    .append(title).append(", content=").append(content).append("]"); 
            return builder.toString(); 
        } 
         
    } 

       这个Email对象包含了一个简单的接收者email地址、邮件主题和邮件内容。我们在发送的时候就把这个对象封装成一个ObjectMessage进行发送。代码如下所示:
Java代码  收藏代码

    public class ProducerServiceImpl implements ProducerService { 
      
        @Autowired 
        private JmsTemplate jmsTemplate;     
     
        public void sendMessage(Destination destination, final Serializable obj) { 
            jmsTemplate.send(destination, new MessageCreator() { 
      
                public Message createMessage(Session session) throws JMSException { 
                    ObjectMessage objMessage = session.createObjectMessage(obj); 
                    return objMessage; 
                } 
                 
            }); 
        } 
      
    } 

       这是对应的在没有使用MessageConverter的时候我们需要new一个MessageCreator接口对象,然后在其抽象方法createMessage内部使用session创建一个对应的消息。在使用了MessageConverter的时候我们在使用JmsTemplate进行消息发送时只需要调用其对应的convertAndSend方法即可。如:


Java代码  收藏代码

    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接口即可。我们先来看一下MessageConverter接口的定义:
Java代码  收藏代码

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

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


Java代码  收藏代码

    import javax.jms.JMSException; 
    import javax.jms.Message; 
    import javax.jms.ObjectMessage; 
    import javax.jms.Session; 
      
    import org.springframework.jms.support.converter.MessageConversionException; 
    import org.springframework.jms.support.converter.MessageConverter; 
      
    public class EmailMessageConverter implements MessageConverter { 
      
        public Message toMessage(Object object, Session session) 
                throws JMSException, MessageConversionException { 
            return session.createObjectMessage((Serializable) object); 
        } 
      
        public Object fromMessage(Message message) throws JMSException, 
                MessageConversionException { 
            ObjectMessage objMessage = (ObjectMessage) message; 
            return objMessage.getObject(); 
        } 
      
    } 



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

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


Xml代码  收藏代码

    <!-- 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="com.tiantian.springintejms.converter.EmailMessageConverter"/> 

   

       到此我们的MessageConverter就定义好了,也能够进行使用了,接着我们来进行测试一下,定义测试代码如下所示:


Java代码  收藏代码

    @Test 
    public void testObjectMessage() { 
        Email email = new Email("zhangsan@xxx.com", "主题", "内容"); 
        producerService.sendMessage(destination, email); 
    } 



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


Java代码  收藏代码

    public class ConsumerMessageListener 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代码  收藏代码

    public class ConsumerMessageListener implements MessageListener { 
      
        private MessageConverter messageConverter; 
         
        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) messageConverter.fromMessage(objMessage); 
                    System.out.println("接收到一个ObjectMessage,包含Email对象。"); 
                    System.out.println(email); 
                } catch (JMSException e) { 
                    e.printStackTrace(); 
                } 
                 
            } 
        } 
      
        public MessageConverter getMessageConverter() { 
            return messageConverter; 
        } 
      
        public void setMessageConverter(MessageConverter messageConverter) { 
            this.messageConverter = messageConverter; 
        } 
      
    } 



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


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" ref="emailMessageConverter"/> 
    </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> 



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


Java代码  收藏代码

    public class ConsumerListener { 
      
        public void receiveMessage(String message) { 
            System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message); 
        } 
         
        public void receiveMessage(Email email) { 
            System.out.println("接收到一个包含Email的ObjectMessage。"); 
            System.out.println(email); 
        } 
         
    } 



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


Java代码  收藏代码

    @Test 
    public void testObjectMessage() { 
        Email email = new Email("zhangsan@xxx.com", "主题", "内容"); 
        producerService.sendMessage(adapterQueue, email); 
    } 



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

        说到这里可能有读者就会有疑问了,说我们在之前讲解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的创建。

这里我们也来看一下SimpleMessageConverter的定义,如果觉得它不能满足你的要求,那我们可以对它里面的部分方法进行重写,或者是完全实现自己的MessageConverter。
Java代码  收藏代码

    public class SimpleMessageConverter implements MessageConverter { 
      
        public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { 
            if (object instanceof Message) { 
                return (Message) object; 
            } 
            else if (object instanceof String) { 
                return createMessageForString((String) object, session); 
            } 
            else if (object instanceof byte[]) { 
                return createMessageForByteArray((byte[]) object, session); 
            } 
            else if (object instanceof Map) { 
                return createMessageForMap((Map) object, session); 
            } 
            else if (object instanceof Serializable) { 
                return createMessageForSerializable(((Serializable) object), session); 
            } 
     
            else { 
                throw new MessageConversionException("Cannot convert object of type [" + 
                        ObjectUtils.nullSafeClassName(object) + "] to JMS message. Supported message " + 
                        "payloads are: String, byte array, Map<String,?>, Serializable object."); 
            } 
        } 
      
        public Object fromMessage(Message message) throws JMSException, MessageConversionException { 
            if (message instanceof TextMessage) { 
                return extractStringFromMessage((TextMessage) message); 
            } 
            else if (message instanceof BytesMessage) { 
                return extractByteArrayFromMessage((BytesMessage) message); 
            } 
            else if (message instanceof MapMessage) { 
                return extractMapFromMessage((MapMessage) message); 
            } 
            else if (message instanceof ObjectMessage) { 
                return extractSerializableFromMessage((ObjectMessage) message); 
            } 
            else { 
                return message; 
            } 
        } 
      
        protected TextMessage createMessageForString(String text, Session session) throws JMSException { 
            return session.createTextMessage(text); 
        } 
      
        protected BytesMessage createMessageForByteArray(byte[] bytes, Session session) throws JMSException { 
            BytesMessage message = session.createBytesMessage(); 
            message.writeBytes(bytes); 
            return message; 
        } 
      
        protected MapMessage createMessageForMap(Map<?, ?> map, Session session) throws JMSException { 
            MapMessage message = session.createMapMessage(); 
            for (Map.Entry entry : map.entrySet()) { 
                if (!(entry.getKey() instanceof String)) { 
                    throw new MessageConversionException("Cannot convert non-String key of type [" + 
                            ObjectUtils.nullSafeClassName(entry.getKey()) + "] to JMS MapMessage entry"); 
                } 
                message.setObject((String) entry.getKey(), entry.getValue()); 
            } 
            return message; 
        } 
      
        protected ObjectMessage createMessageForSerializable(Serializable object, Session session) throws JMSException { 
            return session.createObjectMessage(object); 
        } 
      
      
        protected String extractStringFromMessage(TextMessage message) throws JMSException { 
            return message.getText(); 
        } 
      
        protected byte[] extractByteArrayFromMessage(BytesMessage message) throws JMSException { 
            byte[] bytes = new byte[(int) message.getBodyLength()]; 
            message.readBytes(bytes); 
            return bytes; 
        } 
      
        protected Map extractMapFromMessage(MapMessage message) throws JMSException { 
            Map<String, Object> map = new HashMap<String, Object>(); 
            Enumeration en = message.getMapNames(); 
            while (en.hasMoreElements()) { 
                String key = (String) en.nextElement(); 
                map.put(key, message.getObject(key)); 
            } 
            return map; 
        } 
      
        protected Serializable extractSerializableFromMessage(ObjectMessage message) throws JMSException { 
            return message.getObject(); 
        } 
      
    } 
分享到:
评论

相关推荐

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

    本文将深入探讨Spring与JMS的整合,特别是MessageConverter的概念及其作用。 一、Spring JMS概述 Spring提供了对JMS的全面支持,包括连接工厂配置、消息生产者、消费者以及消息转换器等。JMS允许应用程序通过消息...

    Spring JMS

    Spring JMS Spring JMS 是一个基于 Java 消息服务(JMS)的框架,它提供了一个简洁的...同时,Spring JMS 也提供了许多有用的功能,例如转换 JMSException、MessageConverter、管理 JMS 目标等,以便更好地使用 JMS。

    Java网络编程--基于Spring的JMS编程

    4. **消息转换**:Spring还提供了`MessageConverter`接口,用于在消息对象和应用程序对象之间进行转换,这在处理不同格式的消息时非常有用。 5. **JMS模板的使用**:`JmsTemplate`提供了多种发送消息的方法,如`...

    spring-jms源码

    这涉及到MessageConverter的实现,如SimpleMessageConverter或Jackson2JsonMessageConverter,它们负责对象与JMS消息之间的序列化和反序列化。 2. 事务管理:Spring JMS如何利用JMS的事务特性来保证消息的一致性。...

    spring-jms

    3. **消息转换**: Spring JMS支持消息与应用程序对象之间的转换,通过MessageConverter接口实现。这使得可以将Java对象序列化为消息体,反之亦然。 4. **事务管理**: Spring JMS允许与Spring的声明式事务管理集成,...

    Spring-JMS把企业消息处理变容易.doc

    `org.springframework.jms.support.converter`包则包含了`MessageConverter`接口,用于在Java对象和JMS消息之间进行转换,实现数据的序列化和反序列化。`org.springframework.jms.support.destination`包提供了目标...

    spring整合jms+activemq

    在IT行业中,Spring框架是Java领域最广泛应用的轻量级框架之一,而JMS(Java Message Service)则是一种标准接口,用于在分布式系统中进行异步消息传递。ActivemQ是Apache软件基金会的一个项目,它实现了JMS规范,...

    jms-spring.zip

    - Spring提供MessageConverter接口,可以将消息体在不同格式之间进行转换,如JSON、XML等。 10. **消息持久化**: - ActiveMQ支持消息持久化,即使在服务器重启后,未被消费的消息也能恢复。 通过这个"jms-...

    Spring集成JMS

    在实际应用中,`SpringJMS`可能包含以下示例代码片段: ```xml &lt;bean id="jmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"&gt; &lt;!-- 这里配置具体的JMS提供商实现 --&gt;...

    Spring+JMS+消息处理

    - **消息转换**:`org.springframework.jms.support.converter.MessageConverter`接口可以用于在Java对象和JMS消息之间进行转换。 - **目的地管理**:`org.springframework.jms.support.destination`包提供了一系列...

    Spring整合JMS

    如果消息需要在发送和接收之间进行转换,Spring的`MessageConverter`接口可以帮助我们实现这个功能。它可以将Java对象自动序列化为适合JMS的消息格式,或者反序列化从JMS接收到的消息。 7. **消息驱动的POJO(MDP...

    Spring+weblogic接收JMS消息

    - `applicationContext-jms.xml`是Spring配置文件,通常包含JMS相关的bean定义,如`ConnectionFactory`、`Destination`(队列或主题)、`MessageListenerContainer`以及`MessageConverter`等。 - `...

    spring集成JMS

    Spring框架作为一个强大的企业级应用开发框架,提供了对JMS的全面支持,使得开发者能够方便地在Spring应用中集成JMS,实现异步消息处理和高可用性。 一、JMS简介 JMS是一种API,用于在分布式环境中发送、接收和管理...

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

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

    JMS-Spring

    Spring框架提供了对JMS的全面支持,使得开发者可以方便地集成和管理消息传递系统。在本文中,我们将探讨如何在Spring中使用JMS进行异步传输,以及与ActiveMQ的结合实例。 首先,我们需要配置Spring的JMS支持。在...

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

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

    jms simple code

    在“SpringJMS”中,Spring框架提供了对JMS的高级抽象和简化配置。以下是一些关键点: - **Spring JMS Template**:这是Spring提供的一个工具类,简化了发送和接收JMS消息的过程。它封装了创建会话、创建消息和发送...

    spring-messaging源码

    Spring Messaging是Spring框架的一部分,它为处理消息传递提供了统一的抽象,支持多种消息传递协议,如JMS(Java Message Service)、AMQP(Advanced Message Queuing Protocol)以及STOMP(Simple Text Oriented ...

    Spring in action 3.0

    Spring 3.0版本引入了许多新的功能和增强,包括对Java EE 6的支持、对RESTful Web服务的全面支持、增强的AOP(面向切面编程)功能、对JMS(Java消息服务)和JMX(Java管理扩展)的改进,以及对动态语言的支持等。...

    JMS入门Demo

    实现MessageConverter接口来转换JMS对象与java对象.. 其实在使用MessageListenerAdapter时,Spring默认为我们提供了SimpleMessageConverter转换器.. 事务(无代码): 在Spring整合JMS的应用中,如果我们要进行本地...

Global site tag (gtag.js) - Google Analytics