消息转换器
AmqpTemplate同样定义了一些发送和接收消息的方法,这些方法委托MessageConverter来完成。MessageConverter自身很直观,它为每个方向都提供了一个方法:一个是转为Message,一个是从Message转出为。注意当转为Message的时候除了实体,你还需要提供一些附加属性,‘objects'一般情况下对应着消息体。
public interfaceMessageConverter {
Message toMessage(Object object, MessageProperties messageProperties)
throwsMessageConversionException;
Object fromMessage(Message message) throwsMessageConversionException;
}
AmqpTemplate中与发送相关的函数如下表所示。它们比我们先前看到的方法要明显简单,因为它们不需要消息实例。取而代之的是,MessageConverter将提供的对象转为字节数组,并添加消息属性了创建这个消息实例。
voidconvertAndSend(Object message) throwsAmqpException;
voidconvertAndSend(String routingKey, Object message) throwsAmqpException;
voidconvertAndSend(String exchange, String routingKey, Object message)
throwsAmqpException;
voidconvertAndSend(Object message, MessagePostProcessor messagePostProcessor)
throwsAmqpException;
voidconvertAndSend(String routingKey, Object message,
MessagePostProcessor messagePostProcessor) throwsAmqpException;
voidconvertAndSend(String exchange, String routingKey, Object message,
MessagePostProcessor messagePostProcessor) throwsAmqpException;
在接收端,只有两个方法;一个需要队列的名称,另一个不需要,但是需要在template上设置queue属性。
Object receiveAndConvert() throwsAmqpException;
Object receiveAndConvert(String queueName) throwsAmqpException;
注意:
MessageListenerAdapter中同样使用到了MessageConverter。
SimpleMessageConverter
MessageConverter的默认实现是SimpleMessageConverter。如果你没有为RabbitTemplate显示的指定一个,那么它将使用
SimpleMessageConverter。它处理基于文本的内容,序列化Java对象,和字节数组。
转换Message
如果输入消息的content type是以text开始,它同样会检查content-encoding这个属性来决定将Message body的字节数组转为Java字符串时,要采用的字符集。如果content-encoding属性没有设置,默认使用UTF-8字符集。如果你想覆盖默认的设置,你可以配置一个SimpleMessageConverter实例,设置它的默认字符集实例,然后将它注入到RabbitTemplate实例中。
如果你将输入消息的content-type设置为’application/x-java-serialized-object
‘,则SimpleMessageConverter将尝试将字节数组反序列化为Java对象。它为与简单的类型也许会有帮助,通常不推荐使用使用Java序列化,因为这样是的生产者与消费者愈合很紧。当然如果在一段不适用Java体系,那么将失去控制。因为AMQP是wire-level的协议,使用这个限制会丢失它的优越性。在下面两个部分,我们将探索在不使用Java序列化的基础上传递领域对象的其他方法。
对于其他的一些content-type,
SimpleMessageConverter直接将消息体内容作为字节数组返回。
转为Message
当将任意的Java对象转换为Message时,
SimpleMessageConverter同样处理着,字节数组,字符串和序列化实例。它会将每一个都转为字节数组,它也会相应的设置content-type这个属性。如果要转换的对象与以上类型不匹配,那么消息体将为空。
Json转换器:JsonMessageConverter 和Jackson2JsonMessageConverter
像前一节中提及的那样,依赖Java 序列化不被推荐。一种更为灵活的解决方案是使用JSON转换器。JSON转换器目前已有两个实现可用,可以在RabbitTemplate上进行配置来取代默认的SimpleMessageConverter配置。JsonMessageConverter使用org.codehaus.jackson 1.x库,Jackson2JsonMessageConverter使用com.fasterxml.jackson 2.x库。
<bean class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<property name="connectionFactory" ref="rabbitConnectionFactory"/>
<property name="messageConverter">
<bean class="org.springframework.amqp.support.converter.JsonMessageConverter">
<!-- if necessary, override the DefaultClassMapper -->
<property name="classMapper" ref="customClassMapper"/>
</bean>
</property>
</bean>
<bean class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<property name="connectionFactory" ref="rabbitConnectionFactory"/>
<property name="messageConverter">
<bean class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter">
<!-- if necessary, override the DefaultClassMapper -->
<property name="classMapper" ref="customClassMapper"/>
</bean>
</property>
</bean>
如上面所述,
JsonMessageConverter和
Jackson2JsonMessageConverter
默认会使用DefaultClassMapper。信息会被添加到消息属性中。如果收到的消息在消息属性中没有包含类型信息,但是你知道期望的类型,你可以通过defaultType属性进行设置。
<bean id="jsonConverterWithDefaultType"
class="o.s.amqp.support.converter.JsonMessageConverter">
<property name="classMapper">
<bean class="org.springframework.amqp.support.converter.DefaultClassMapper">
<property name="defaultType" value="foo.PurchaseOrder"/>
</bean>
</property>
</bean>
<bean id="jsonConverterWithDefaultType"
class="o.s.amqp.support.converter.Jackson2JsonMessageConverter">
<property name="classMapper">
<bean class="org.springframework.amqp.support.converter.DefaultClassMapper">
<property name="defaultType" value="foo.PurchaseOrder"/>
</bean>
</property>
</bean>
MarshallingMessageConverter
另外一个转换器是MarshallingMessageConverter转换器,它使用Spring OXM类库(它们实现了Marshaller和Unmarshller接口)。在配置的时候,大多数情况下是在构造参数中进行配置。
<bean class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<property name="connectionFactory" ref="rabbitConnectionFactory"/>
<property name="messageConverter">
<bean class="org.springframework.amqp.support.converter.MarshallingMessageConverter">
<constructor-arg ref="someImplemenationOfMarshallerAndUnmarshaller"/>
</bean>
</property>
</bean>