RabbitMQ基础篇之Java客户端 消息转换器
文章目录
- 消息转换器简介
- RabbitTemplate 的 convertAndSend() 方法
- 消息转换器的工作原理
- JDK 序列化的缺点
- 改进:使用 JSON 进行序列化
- 实现步骤
- 示例:发送Map类型的消息
- 接收消息
- 验证与测试
- 总结
消息转换器简介
消息转换器(Message Converter)是Spring AMQP中的一个重要组件,用于处理消息的序列化和反序列化。具体来说,它负责将Java对象转换为字节序列发送到RabbitMQ,并在消息接收时将字节序列反序列化回Java对象。
RabbitTemplate 的 convertAndSend() 方法
在Spring AMQP中,使用convertAndSend()
方法来发送消息。此方法的最后一个参数是一个 Object 类型,意味着我们可以发送任何Java对象。convertAndSend()
方法不仅发送消息,还会将消息对象转换为可以在网络上传输的字节流。
public void convertAndSend(String exchange, String routingKey, Object message);
其中,message
可以是字符串、集合或任何自定义Java对象,convertAndSend()
会将这些对象转为字节流发送给RabbitMQ。
消息转换器的工作原理
Spring AMQP的消息转换器会将Java对象转化为字节流,进行网络传输。当消息从RabbitMQ接收到时,字节流会通过消息转换器被反序列化为Java对象。
默认行为:
- 发送消息时:消息会通过
SimpleMessageConverter
转换为字节流。 - 接收消息时:消息会被自动反序列化回Java对象。
默认的序列化方式:Spring AMQP默认使用JDK自带的序列化机制。消息格式为 application/x-java-serialized-object
。
JDK 序列化的缺点
默认的 JDK 序列化虽然可以转换任意对象,但它存在几个显著的问题:
- 安全漏洞:JDK序列化存在反序列化攻击的风险。
- 体积过大:序列化后的字节流体积较大,占用带宽和存储空间。
- 可读性差:序列化后的字节流不可读,无法直观查看消息内容。
改进:使用 JSON 进行序列化
为了避免JDK序列化的缺点,可以使用JSON作为消息的序列化格式,这样:
- 数据体积较小。
- 数据可读性好。
- 提高了消息的安全性。
如何实现:
- 使用Jackson库将消息序列化为JSON格式。
- 配置
Jackson2JsonMessageConverter
替代默认的SimpleMessageConverter
。
实现步骤
- 引入Jackson依赖 首先需要在项目中引入Jackson的依赖。
<!-- jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
- 配置消息转换器 在Spring的配置类中配置
Jackson2JsonMessageConverter
作为消息转换器。
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
- 自动注入到
RabbitTemplate
配置好消息转换器后,Spring Boot会自动将该转换器注入到RabbitTemplate
中,确保发送和接收消息时使用相同的转换器。 - 消息监听者和消费者都需要配置。
示例:发送Map类型的消息
假设我们需要发送一个包含姓名和年龄的Map对象,通过RabbitTemplate发送消息。
发送消息代码:
@Test
public void testSendObject() {;
// 消息
Map<String, Object> msg = new HashMap<>(2);
msg.put("name", "jack");
msg.put("age", 20);
// 发送消息
rabbitTemplate.convertAndSend("object.queue", msg);
}
发送后在RabbitMQ中的格式:
- 发送的消息会被转换为JSON格式:
{"name":"Jack","age":21}
- 此时消息的Content-Type会变为
application/json
,并且消息体积更小且可读性更高。
接收消息
接收方只需要使用相同的消息转换器来处理消息:Spring会根据消息的Content-Type自动选择正确的消息转换器进行反序列化。
消费者代码示例:
@RabbitListener(queues = "object.queue")
public void listenObjectQueue(Map<String, Object> message) {
log.info("消费者接收到 object.queue 的消息: " + message);
}
此时,消费者能够正确地反序列化收到的JSON格式的消息。
验证与测试
在进行消息发送和接收时,要确保发送端和接收端使用的是相同的消息转换器。否则,如果发送端使用了JSON格式,而接收端使用了JDK序列化格式,会导致反序列化失败。
测试步骤:
- 发送消息时使用
Jackson2JsonMessageConverter
转换为JSON格式。 - 在RabbitMQ控制台查看消息时,确认消息体为JSON格式。
- 消费者接收到消息后,正确反序列化为Map对象。
总结
- 默认序列化方式:Spring AMQP默认使用JDK的序列化方式,它在一些场景下并不理想,特别是在安全性、体积和可读性方面。
- 推荐使用JSON序列化:通过引入
Jackson2JsonMessageConverter
替代JDK序列化,可以有效提升消息的可读性,减少消息体积,并避免安全问题。 - 配置步骤:只需要引入Jackson依赖并配置
Jackson2JsonMessageConverter
,Spring Boot会自动注入转换器,无需手动配置每个RabbitTemplate
。