消息类型转换

为了方便域模型对象的发送,JmsTemplate有各种发送方法,这些方法将Java对象作为消息数据内容的参数。

JmsTemplate中的convertAndSend()和receiveAndConvert()重载方法将转换过程委托给MessageConverter接口的实例。

这个接口定义了一个简单的契约,用于在Java对象和JMS消息之间进行转换。

默认实现SimpleMessageConverter支持字符串和TextMessage、byte[]和BytesMesssage以及java.utiljava.util.Map 之间的转换和MapMessage。

通过使用转换器,您和应用程序代码可以关注通过JMS发送或接收的业务对象,而不关心如何将其表示为JMS消息的细节。

沙箱目前包括一个MapMessageConverter,它使用反射在JavaBean和MapMessage之间进行转换。您可能自己实现的其他流行的实现选择是使用现有XML编组包(如JAXB、Castor、XMLBeans或XStream)的转换器来创建表示对象的TextMessage。

为了适应不能在转换器类中通用封装的消息属性、报头和正文的设置,MessagePostProcessor接口允许您在消息被转换之后(但在发送之前)访问消息。下面的示例演示如何在java.util之后修改消息头和属性。映射被转换为消息。

示例代码

代码

  • Email.java

定义一个对象实体。

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Email implements Serializable { private static final long serialVersionUID = -209247729960531557L; 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; } //Getter & Setter //toString() }
  • EmailMessageConverter.java

定义 Email 对应的转换器

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
public class EmailMessageConverter implements MessageConverter { @Override public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { return session.createObjectMessage((Serializable) object); } @Override public Object fromMessage(Message message) throws JMSException, MessageConversionException { ObjectMessage objMessage = (ObjectMessage) message; return objMessage.getObject(); } }

这样,我们在发送消息和接受消息的时候,就可以变得简洁。

  • 发送消息
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service public class ConvertorProducerImpl { @Autowired private JmsTemplate jmsTemplate; @Autowired private Destination destination; public void send(final Serializable object) { // convertAndSend() 会调用具体的 convertor 转换方法 jmsTemplate.convertAndSend(destination, object); } }
  • 接受消息
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ConvertorConsumerListener implements MessageListener { @Autowired private MessageConverter messageConverter; @Override public void onMessage(Message message) { if (message instanceof ObjectMessage) { ObjectMessage objMessage = (ObjectMessage) message; try { Email email = (Email) messageConverter.fromMessage(objMessage); System.out.println("接收到一个ObjectMessage,包含Email对象。"); System.out.println(email); } catch (JMSException e) { e.printStackTrace(); } } } }

配置文件

  • application-mq-convertor.xml
  [xml]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--扫描路径--> <context:component-scan base-package="com.github.houbb.jms.learn.activemq.spring.convertor"/> <!-- 类型转换器 --> <bean id="emailMessageConverter" class="com.github.houbb.jms.learn.activemq.spring.convertor.EmailMessageConverter"/> <!-- 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> <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供--> <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://127.0.0.1:61616"/> </bean> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> <property name="targetConnectionFactory" ref="targetConnectionFactory"/> </bean> <!--这个是队列目的地--> <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg> <value>queue</value> </constructor-arg> </bean> <!--消息监听器--> <bean id="consumerMessageListener" class="com.github.houbb.jms.learn.activemq.spring.convertor.ConvertorConsumerListener"/> <!-- 消息监听容器 --> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="destination" ref="queueDestination"/> <property name="messageListener" ref="consumerMessageListener"/> </bean> </beans>

测试代码

  • MessageConvertorTest.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.junit.Test; import org.junit.runner.RunWith; 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.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.Session; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:application-mq-convertor.xml") public class MessageConvertorTest { @Autowired private ConvertorProducerImpl convertorProducer; @Test public void sendMsg() { Email email = new Email("Dear MQ", "MQ 转换测试", "一些内容"); convertorProducer.send(email); } }
  • 测试日志
  [plaintext]
1
2
接收到一个ObjectMessage,包含Email对象。 Email{receiver='Dear MQ', title='MQ 转换测试', content='一些内容'}

源码地址

spring 转换器

参考资料

jms-msg-conversion

消息转换器 MessageConverter