Spring integrates JMS's MessageConverter

Message Converter MessageConverter

      MessageConverter has two main functions. On the one hand, it can convert our non-standardized Message object into our target Message object, which is mainly used when sending messages; on the other hand, it can convert our The Message object is converted into the corresponding target object, which is mainly used when receiving messages.

     Let's take sending an object message as an example. Suppose we have such a requirement: our platform has a function of sending mail. When sending, we just encapsulate our relevant information into a JMS message, and then use JMS to send it. The message is actually sent when the corresponding message listener processes the received message.

Suppose we have such an Email object:


Java code collection code

    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 + " ]"; 
        } 
         
    } 

 


This Email object contains a simple recipient email address, email subject and email content. When we send, we encapsulate this object into an ObjectMessage for sending. When using MessageConverter, we only need to call its corresponding convertAndSend method when using JmsTemplate for message sending. The code is as follows:
Java code Collection code

    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) { 
             //If MessageConverter is not used   
    // jmsTemplate.send(destination, new MessageCreator() { 
    // public Message createMessage(Session session) throws JMSException { 
    // ObjectMessage objMessage = session .createObjectMessage(obj);   
    // return objMessage;   
    // } 
    // }); 
          //In the case of using MessageConverter 
            jmsTemplate.convertAndSend(destination, obj);   
        }  
    } 


  so that JmsTemplate will internally call the scheduled MessageConverter to our The message object is converted and then sent.

       At this time we need to define our MessageConverter. It is very simple to define your own MessageConverter, just implement the MessageConverter interface provided by Spring. Let's first look at the definition of the Spring MessageConverter interface:


Java code Collection code

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

We can see that two methods fromMessage and toMessage and fromMessage are used to convert a JMS Message into a corresponding Java object, and the toMessage method is used to convert a Java object into a corresponding JMS Message. Because we already know that the object to be sent above is an Email object, here we simply define an EmailMessageConverter to convert the Email object and the corresponding ObjectMessage. The code is as follows:
Java code Collection code

    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; 
        } 
    } 



       so that when we use the convertAndSend method of JmsTemplate to send When an Email object is used, the toMessage method of our defined EmailMessageConverter will be called with the corresponding Email object as a parameter.

       After defining our EmailMessageConverter, we need to specify that the messageConverter of the JmsTemplate object we use to send the Email object is EmailMessageConverter. Here we specify when we define the JmsTemplate bean in the Spring configuration file:




Java code Collection code

    <!-- Spring provided JMS tool class, which can send and receive messages, etc. --> 
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> 
            <!-- This connectionFactory corresponds to the ConnectionFactory object we defined by Spring --> 
            <property name="connectionFactory" ref ="connectionFactory" /> 
            <!-- Message Converter-->   
            <property name="messageConverter" ref="emailMessageConverter"/>   
        </bean> 
     
    <!-- Type Converter-->   
        <bean id="emailMessageConverter " class="cn.tzz.jms.activemq.spring.obj.service.impl.EmailMessageConverter"/> At   




this point, our MessageConverter is defined and can be used.

       The MessageListener method for receiving processing corresponding to the above destination is as follows:



Java code Collection code

    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(); 
                } 
            } 
        } 
      
    } 



       As mentioned earlier, MessageConverter has two functions. In addition to converting Java objects into corresponding Jms Messages, it can also convert Jms Messages into corresponding Java objects. We see that the message listener above receives a Jms Message when it receives a message. If we want to use MessageConverter to convert it into a corresponding Java object, we can only inject a corresponding MessageConverter into it, and then in Manual calls in it, such as:



Java code collection code

    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; 
        } 
    } 



       When we use MessageListenerAdapter as a message listener, we can specify a corresponding MessageConverter for it, so that Spring When processing the received message, it will be automatically converted by our specified MessageConverter, and then the specified message processing method will be called with the converted Java object as a parameter. Here we use the MessageListenerAdapter defined in the previous explanation of the MessageListenerAdapter as a test, and we specify its MessageConverter as our defined EmailMessageConverter.



Xml code Collection code

     <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> 
         
     
        <!-- The JMS tool class provided by Spring, which can send and receive messages --> 
        <bean id="jmsTemplate" class=" org.springframework.jms.core.JmsTemplate"> 
            <!-- This connectionFactory corresponds to the ConnectionFactory object we defined by Spring --> 
            <property name="connectionFactory" ref="connectionFactory" /> 
            <!-- Message Converter -->   
            <property name="messageConverter" ref="emailMessageConverter"/>   
        </bean> 
        <!--Message queue destination, peer-to-peer --> 
        <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>  Java code Collection code



       Then add a receiveMessage method in our ConsumerListener that is actually used to process the received message, and the code after adding it is as follows:




    public class ConsumerListener { 
      
        public void handleMessage(String message) { 
            System.out.println("ConsumerListener received a message through handleMessage: " + message); 
        } 
    // public void receiveMessage(String message) { 
    // System.out.println( "ConsumerListener received message via receiveMessage: " + message); 
    // } 
    // public String receiveMessage(String message) { 
    // System.out.println("ConsumerListener received message via receiveMessage: " + message); 
    // return "This is the return value of the receiveMessage method of the ConsumerListener object.";   
    // } 
         
        public void receiveMessage(Email email) {   
            System.out.println("Received an ObjectMessage containing Email.");   
            System.out.println(email);   
        }   
    } 



       Then we define the following test code:



Java code Collection code

    @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("[email protected]", "test", "HellWorld"); 
            entityProducerService.sendMessage(adapterQueue, email); 
        } 
    } 



       Because we have specified a MessageConverter for MessageListenerAdapter, and it is an EmailMessageConverter, so when After the MessageListenerAdapter receives a message, it will call the fromMessage method of the specified MessageConverter to convert it into a Java object. According to the definition, it will be converted into an Email object, and then the Email object will be used as a parameter to call the one we specified through the defaultListenerMethod property. The default processor method, according to the definition, here is the receiveMessage method, but we can see that we have defined two receiveMessage methods in the ConsumerListener, because the method is called through the converted Email object as a parameter, so the call here should be It is the receiveMessage method whose parameter type is Email.

The above test code will output the following results after running:

an ObjectMessage is received, including the Email object.

Email [[email protected], title=test, content=HellWorld]


        When it comes to this, some readers may have doubts, saying that we did not specify the corresponding MessageConverter when we explained the MessageListenerAdapter before, and then sent a TextMessage. As a result, Spring still converted it into a String object, and called the ConsumerListener parameter type of String's receiveMessage method? Then your MessageConverter is useless when MessageListenerAdapter receives messages.

       In fact, it is still useful. When we use MessageListenerAdapter, when we initialize it, that is, call its constructor, it will default to a new MessageConverter that Spring has already implemented for us - SimpleMessageConverter as its default MessageConverter, which is why The reason why we don't need to specify MessageConverter when using MessageListenerAdapter but the message will still be converted into the corresponding Java object. So by default, when we use MessageListenerAdapter, the handler method parameter type of the corresponding MessageListener must be a common Java object, not the corresponding Jms Message object.

       So what if we want to use MessageListenerAdapter when dealing with Jms Message, and then want to deal with the original Message instead of the Message converted by MessageConverter? At this time, we only need to specify that its MessageConverter is empty when defining the MessageListenerAdapter.



Xml code Favorite code

    <!-- Message monitoring adapter--> 



















        System.out.println(message.getObject()); 
    } 



       Just mentioned that Spring has implemented a simple MessageConverter for us, namely org.springframework.jms.support.converter.SimpleMessageConverter, in fact, Spring also specified when initializing JmsTemplate The corresponding MessageConverter is a SimpleMessageConverter, so if we don't have any special requirements, we can directly use the convertAndSend series methods of JmsTemplate to send messages, instead of tediously creating a new MessageCreator when calling the send method.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326494813&siteId=291194637