消息转换器
Spring的消息发送代码接收的消息体是一个Object:
而在数据传输时,它会把你发送的消息序列化为字节发送给MQ,接收消息的时候,还会把字节反序列化为Java对象。
只不过,默认情况下Spring采用的序列化方式是JDK序列化。众所周知,JDK序列化存在下列问题:
- 数据体积过大
- 有安全漏洞
- 可读性差
我们来测试一下。
测试默认转换器
创建测试队列
我们在consumer服务中声明一个配置类,MessageConfig,里面编写方法创建队列。
java
@Configuration
public class MessageConfig {
@Bean
public Queue objectQueue(){
return new Queue("object.queue");
}
}
重启consumer服务,看看rabbit控制台。
发送map消息
在consumer服务中,新增ObjectQueueTest类,发送消息。
java
@SpringBootTest
public class ObjectQueueTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSendObjectQueue(){
// 1 队列
String queueName = "object.queue";
// 2 消息
Map<String,Object> map = new HashMap<>();
map.put("name","sde");
map.put("age",18);
// 3 发送消息
rabbitTemplate.convertAndSend(queueName,map);
}
}
看看控制台是否有消息
查看消息
可以看到消息格式非常不友好。
配置JSON转换器
添加依赖
显然,JDK序列化方式并不合适。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。
在publisher和consumer两个服务中都引入依赖
XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
注意:如果项目中引入了spring-boot-starter-web依赖,则无需再次引入Jackson依赖。
配置消息转换器
配置消息转换器,在publisher和consumer两个服务的启动类中添加一个Bean即可。
在PublisherApplication启动类中添加
java
@SpringBootApplication
public class PublisherApplication {
public static void main(String[] args) {
SpringApplication.run(PublisherApplication.class);
}
@Bean
public MessageConverter messageConverter(){
// 1 定义消息转换器
Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();
//2、配置每条消息自动创建id;用于识别不同消息,也可以在页面中基于id判断是否是重复消息
jjmc.setCreateMessageIds(true);
return jjmc;
}
}
在ConsumerApplication 启动类添加如下
java
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public MessageConverter messageConverter(){
// 1 定义消息转换器
Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();
//2、配置每条消息自动创建id;用于识别不同消息,也可以在页面中基于id判断是否是重复消息
jjmc.setCreateMessageIds(true);
return jjmc;
}
}
测试
① 在rabbitMQ的控制台中删除 object.queue 队列中的消息;重新启动 consumer
② 执行 com.sde.publisher.ObjectQueueTest类里面的方法,发送消息。
③ 在rabbitMQ的控制台中;查看消息
删除队列里面的消息
重启了 consumer服务
再次发送了一条消息
控制台查看消息
消费者接收Object
我们在consumer服务中定义一个新的消费者,publisher是用Map发送,那么消费者也一定要用Map接收。
新创建 ObjectQueueListener 类,编写代码接收消息。
java
@Slf4j
@Component
public class ObjectQueueListener {
/**
* 监听 object.queue 队列中的消息。
*/
@RabbitListener(queues = "object.queue")
public void listenObjectQueue(Map<String,Object> map){
System.out.println("【消费者】监听到 object.queue 队列的消息:"+map);
}
}
控制台