新聞中心
改版:

創(chuàng)新互聯(lián)是專業(yè)的鄉(xiāng)寧網(wǎng)站建設公司,鄉(xiāng)寧接單;提供成都網(wǎng)站建設、網(wǎng)站建設,網(wǎng)頁設計,網(wǎng)站設計,建網(wǎng)站,PHP網(wǎng)站建設等專業(yè)做網(wǎng)站服務;采用PHP框架,可快速的進行鄉(xiāng)寧網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
發(fā)送消息與訂閱消息取消使用amqp提供的消息序列化與反序列化功能,使用String類型,發(fā)送消息時手動轉化為json字符串再發(fā)送,消費消息時手動json反序列化。
背景:
如果使用自動序列化與反序列化功能,即給Rabbitmq配置Jackson2JsonMessageConverter消息轉化器,當我們修改消息Body的java類型名稱或者包名時,消費歷史消息就會拋出ClassNotFoundException異常。
1、不做兼容上線,但需要:
- 確保不會有新的消息進入隊列;
- 確保隊列中的消息已經(jīng)消費完。
2、粗暴方式,直接清空隊列,丟棄歷史消息;
3、做兼容,給舊消息創(chuàng)建一個類名匹配的消息Body類型,添加一個@RabbitHandler方法處理舊消息。
這是因為Rabbitmq為了實現(xiàn)一個隊列支持多個方法消費(即@RabbitHandler注解的方法),每個方法消費不同Java類型的消息Body,在消費到消息時,就需要先反序列化出消息Body,才能根據(jù)消息Body的類型去匹配一個消費方法消費消息,如DelegatingInvocableHandler#invoke方法源碼所示。
- // org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler#invoke
- public InvocationResult invoke(Message> message, Object... providedArgs) throws Exception {
- // 獲取消息body類型
- Class extends Object> payloadClass = message.getPayload().getClass();
- // 匹配的方法
- InvocableHandlerMethod handler = getHandlerForPayload(payloadClass);
- // 調(diào)用方法消費
- Object result = handler.invoke(message, providedArgs);
- //....
- }
由于需要在匹配消息消費方法之前就需要解析出消息Body,也就是要先知道消息Body的Java類型才能實現(xiàn)json反序列化,這就要求消息生產(chǎn)者在發(fā)送消息時不得不在消息頭添加一個參數(shù)表示消息Body的Java類型,如下圖所示。
在消息消費階段,Jackson2JsonMessageConverter也需要先根據(jù)消息頭的TypeId獲取JavaType,再執(zhí)行反序列化操作,當類名修改時,或者生產(chǎn)者和消費者各自定義的類名不同,都將會導致反序列化失敗。
除非確保消息Body的類名不會變,且生產(chǎn)者與消費者定義的完整類名相同,否則不建議使用自動序列化與反序列化功能。
本文轉載自微信公眾號「Java藝術」,作者wujiuye 。轉載本文請聯(lián)系Java藝術公眾號。
網(wǎng)站名稱:為什么我不推薦你使用RabbitMQ的消息轉換功能
當前地址:http://m.fisionsoft.com.cn/article/dpjphpj.html


咨詢
建站咨詢
