目录
一、问题背景
二、从消息转化器根源解决问题
1.引入依赖
2.在服务生产者和消费者中都重新定义一个 MessageConverter,注入到 Spring 容器中
一、问题背景
在SpringAMQP的发送方法中,接收消息的类型是Object,也就是说我们可以发送任意对象类型的消息,接下来做个小实验
如下,注入一个队列到容器中,接着在提供一个服务生产者供测试,发送一个对象数据,观察 RabbitMQ 客户端队列数据形式
@Configuration
public class FanoutConfig {@Beanpublic Queue objectQueue() {return new Queue("object.queue");}}
@Testpublic void testObjectMessage() {HashMap<String, Object> map = new HashMap<>();map.put("国家", "china");rabbitTemplate.convertAndSend("object.queue", map);}
运行后,查看 RabbitMQ 队列数据如下:
为什么发送的消息变成了这个样子呢?
这是因为SpringAMQP会帮我们序列化为字节后发送:Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter 来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。
但是这样的数据就有可能引发以下两种问题:
- 转化后数据过长,影响传输效率。
- 容易引发 sql 注入问题。
二、从消息转化器根源解决问题
我们只需要在服务生产者和消费者的 Spring 启动类中都重新定义一个 MessageConverter 类型的Bean即可。这里推荐用JSON方式序列化~
具体步骤如下:
1.引入依赖
因为服务生产者和服务消费者都需要 JSON 来序列化和反序列化,因此直接在的父类中引入依赖即可
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
2.在服务生产者和消费者中都重新定义一个 MessageConverter,注入到 Spring 容器中
使用 @Bean 注解注入即可
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Beanpublic MessageConverter jsonMessageConverter() {return new Jackson2JsonMessageConverter();}}
@SpringBootApplication
public class PublisherApplication {public static void main(String[] args) {SpringApplication.run(PublisherApplication.class);}@Beanpublic MessageConverter jsonMessageConverter() {return new Jackson2JsonMessageConverter();}}
再尝试发送数据,结果如下:
Ps:注意发送方与接收方必须使用相同的MessageConverter