消息轉換器
Spring的消息發送代碼接收的消息體是一個Object:
而在數據傳輸時,它會把你發送的消息序列化為字節發送給MQ,接收消息的時候,還會把字節反序列化為Java對象。
只不過,默認情況下Spring采用的序列化方式是JDK序列化。眾所周知,JDK序列化存在下列問題:
- 數據體積過大
- 有安全漏洞
- 可讀性差
我們來測試一下。
測試默認轉換器
創建測試隊列
我們在consumer服務中聲明一個配置類,MessageConfig,里面編寫方法創建隊列。
@Configuration
public class MessageConfig {@Beanpublic Queue objectQueue(){return new Queue("object.queue");}
}
重啟consumer服務,看看rabbit控制臺。
發送map消息
在consumer服務中,新增ObjectQueueTest類,發送消息。
@SpringBootTest
public class ObjectQueueTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic 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兩個服務中都引入依賴
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency>
注意:如果項目中引入了spring-boot-starter-web依賴,則無需再次引入Jackson依賴。
配置消息轉換器
配置消息轉換器,在publisher和consumer兩個服務的啟動類中添加一個Bean即可。
在PublisherApplication啟動類中添加
@SpringBootApplication
public class PublisherApplication {public static void main(String[] args) {SpringApplication.run(PublisherApplication.class);}@Beanpublic MessageConverter messageConverter(){// 1 定義消息轉換器Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();//2、配置每條消息自動創建id;用于識別不同消息,也可以在頁面中基于id判斷是否是重復消息jjmc.setCreateMessageIds(true);return jjmc;}}
在ConsumerApplication 啟動類添加如下
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Beanpublic 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 類,編寫代碼接收消息。
@Slf4j
@Component
public class ObjectQueueListener {/*** 監聽 object.queue 隊列中的消息。*/@RabbitListener(queues = "object.queue")public void listenObjectQueue(Map<String,Object> map){System.out.println("【消費者】監聽到 object.queue 隊列的消息:"+map);}
}
控制臺