rabbitmq-spring-boot-start版本優化升級

文章目錄

  • 1.前言
  • 2.優化升級內容
  • 3.依賴
  • 4.使用
    • 4.1發送消息代碼示例
    • 4.2消費監聽代碼示例
    • 4.3 brock中的消息
  • 5.RabbmitMq的MessageConverter消息轉換器
    • 5.1默認行為
    • 5.2JDK 序列化的缺點
    • 5.3使用 JSON 進行序列化
  • 6.總結

1.前言

????由于之前手寫了一個好用的rabbitmq-spring-boot-start啟動器,雖然實現了相關的功能,但是還有一點小問題,這個也是最近在項目中使用我寫的這個組件發現的一個問題,所以修復升級了,maven依賴已經退推送到中央倉庫上了,只需要引入依賴,然后簡單的配置就可以實現發消息了,使用上會有一點需要注意的,請聽下文分解。

2.優化升級內容

????升級了RabbitService類中相關發送MQ消息方法上的String msg的類型改為了Object msg,之前在項目中使用的時候發送消息的時候這個參數是String類型會有啥問題,如果要發送一個對象,將這個對象序列化成JSON字符串,最終消費者監聽的地方反序列化解析不來,因為收到過的是一個String不是一個JSON的字符串,這個字符串中會含有轉義\,還有就是字符串的前后會有一個引號("),導致使用FastJson反序列化解析失敗,下面是發送消息的demo代碼

 Student student = new Student();student.setName("張三");student.setSex("男");student.setAge(18);RabbitTemplate rabbitTemplate = (RabbitTemplate) ZlfMqSpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);rabbitService.sendDelayed(rabbitTemplate, "zlf.delay.test1", "delay.test1.key", JSON.toJSONString(student), 60);

????消費者監聽的地方解析代碼:

    @RabbitHandler@RabbitListener(queues = "zlf.delay.test1", containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0)public void mqConsumer(Message message, Channel channel) throws IOException {String msg = new String(message.getBody(), "UTF-8");try {log.info("mqConsumer=====>msg1:{}", msg);msg = StringEscapeUtils.unescapeJava(msg);log.info("mqConsumer=====>msg2:{}", msg);msg = msg.substring(1, msg.length() - 1);log.info("mqConsumer=====>msg3:{}", msg);if (StringUtils.isNotEmpty(msg)) {Student student = JSON.parseObject(message.getBody(), Student.class);log.info("mqConsumer=====>studen:{}", JSON.toJSONString(student));//TODO 業務處理}} catch (Exception e) {log.error("mqConsumer消費異常:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}//channel.basicNack(); 不ack//channel.basicReject(); 拒絕}

????這種方法雖然可以解決這個消費者反序列化的問題,但是只是對于發送FastJson序列化的對象中的字段不含有特殊的轉義字符,如果有會被StringEscapeUtils.unescapeJava方法去除轉義,我這種處理是業務上發送那個FastJson序列化的對象字段沒有特殊的轉義字符,所以這種搞是可以的,于是乎我就抽了一點時間優化升級了下,然后也寫了個demo測試了一下,非常的耐思。

3.依賴

????下面兩個依賴任選其一引入就可以使用了:

<dependency><groupId>io.gitee.bigbigfeifei</groupId><artifactId>rabbitmq-spring-boot-start</artifactId><version>1.1</version>
</dependency>
或者
<dependency><groupId>io.github.bigbigfeifei</groupId><artifactId>rabbitmq-spring-boot-start</artifactId><version>1.1</version>
</dependency>

4.使用

4.1發送消息代碼示例

????只需要發送一個對象就可以了

 Student student = new Student();student.setName("張三");student.setSex("男");student.setAge(18);RabbitTemplate rabbitTemplate = (RabbitTemplate) ZlfMqSpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);rabbitService.sendDelayed(rabbitTemplate, "zlf.delay.test1", "delay.test1.key", student, 60);

4.2消費監聽代碼示例

/*** 延遲插件實現延遲隊列監聽隊列消息** @param message* @param channel* @throws IOException*/@RabbitHandler@RabbitListener(queues = "delay.test1", containerFactory = ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0)public void mqConsumer1(Message message, Channel channel) throws IOException {try {Student student = JSON.parseObject(message.getBody(), Student.class);log.info("mqConsumer1=====>student:{}", JSON.toJSONString(student));//TODO 業務處理} catch (Exception e) {log.error("mqConsumer1消費異常:{}", e.getMessage());} finally {channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}//channel.basicNack(); 不ack//channel.basicReject(); 拒絕}

4.3 brock中的消息

image-20250423164138770

????本個start使用的是Jackson2JsonMessageConverter消息轉換器來序列化發送消息實體為標準的JSON數據,源碼在ZlfRabbitMqRegistrar類中registerBeanDefinitions方法中,代碼如下:

 //構建發送的RabbitTemplate實例關聯連接工廠Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter);

????為每一個對應的rabbitTemplate對象Bean設置了一個Jackson2JsonMessageConverter消息轉換器,這樣就可以支持JSON數據的序列化和反序列化了。

5.RabbmitMq的MessageConverter消息轉換器

????RabbmitMq默認實現是 SimpleMessageConverter,該類基于 JDK 的 ObjectOutputStream 完成序列化。

5.1默認行為

發送消息時:消息會通過 SimpleMessageConverter 轉換為字節流。
接收消息時:消息會被自動反序列化回Java對象。
默認的序列化方式:Spring AMQP默認使用JDK自帶的序列化機制。消息格式為 application/x-java-serialized-object。

5.2JDK 序列化的缺點

????默認的 JDK 序列化雖然可以轉換任意對象,但它存在幾個顯著的問題:

????安全漏洞:JDK序列化存在反序列化攻擊的風險。
????體積過大:序列化后的字節流體積較大,占用帶寬和存儲空間。
????可讀性差:序列化后的字節流不可讀,無法直觀查看消息內容。

5.3使用 JSON 進行序列化

????為了避免JDK序列化的缺點,可以使用JSON作為消息的序列化格式,這樣:

????數據體積較小。
????數據可讀性好。
????提高了消息的安全性。

????所以默認的 JDK 的 ObjectOutputStream 完成序列化時候該如何處理:

    //  字節碼轉化為對象public Object getObjectFromBytes(byte[] objBytes) throws Exception {if (objBytes == null || objBytes.length == 0) {return null;}ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);ObjectInputStream oi = new ObjectInputStream(bi);return oi.readObject();}

????發送消息時:

Student student = new Student();student.setName("張三");student.setSex("男");student.setAge(18);
byte[] e = getBytesFromObject(student);
Message message = MessageBuilder.withBody(e).setContentType(MessageProperties.CONTENT_TYPE_JSON).build();
//或者直接發一個對象,然后消費監聽的時候從byte[]中讀取反序列化為一個java對象

????消費者監聽調用getObjectFromBytes方法反序列化為一個java對象

 Student student = (Student)getObjectFromBytes(message.getBody());

????這種原始的方式不推薦使用,還是推薦使用JSON的方式。

????MessageConverter接口還有很多的實現類,可以根據你自己的需求去使用或者是自定義一個消息轉換器,這個難度也比較的大,所以也不推薦去搞。

image-20250423170056153

????SimpleRabbitListenerContainerFactory、DirectRabbitListenerContainerFactory、RabbitTemplate這三個類中都有setMessageConverter的方法,只要從容器中獲取對應的Bean,讓然把消息轉換器的對象設置進去就可以了,切入點可以使用一個類實現implements InitializingBean接口,在afterPropertiesSet中取出對應的bean來設置

public void afterPropertiesSet() throws Exception {//設置SimpleRabbitListenerContainerFactory的消息轉換器為Jackson2JsonMessageConverter支持json格式的數據轉換SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory = (SimpleRabbitListenerContainerFactory) ZlfMqSpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.simpleRabbitListenerContainerFactory + 0);simpleRabbitListenerContainerFactory.setMessageConverter(new Jackson2JsonMessageConverter());}

????或者:

RabbitTemplate rabbitTemplate = (RabbitTemplate) ZlfMqSpringUtils.getBean(ZlfMqRegistrarBeanNamePrefix.rabbitTemplatePrefix + 0);rabbitService.sendDelayed(rabbitTemplate, "zlf.delay.test1", "delay.test1.key", JSON.toJSONString(student), 60);

????ZlfMqSpringUtils工具類之前分享的文章里面也有有的叫SpringUtils,有的叫xxxxSpringUtils,都是重復的代碼,復制過去換個名字而已。

6.總結

????雖然只改動了一個參數的類型,但是給使用帶來了很大的便利性,使用更加絲滑,按照這個套路搞一下,分分鐘就集成搞定了,只用專注處理業務了,本次分享到此結束,希望我的分享對你有所啟發和幫助,請一鍵三連,么么么噠!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77956.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git lfs下載大文件限額

起因是用 model.load_state_dict(torch.load())加載pt權重文件時&#xff0c;出現錯誤&#xff1a;_pickle.UnpicklingError: invalid load key, ‘v’. GPT告訴我&#xff1a;你的 pt 文件不是權重文件&#xff0c;而是模型整體保存&#xff08;或根本不是 PyTorch 文件&#…

什么是RAG?RAG的主要流程是什么?

**RAG(Retrieval-Augmented Generation)**是一種結合檢索與生成技術的框架,旨在通過引入外部知識增強生成模型的性能。其核心思想是:在生成文本時,先從外部知識庫中檢索相關信息,再將檢索結果與原始輸入結合,作為生成模型的輸入,從而提升生成內容的準確性、相關性和信息…

【Rust 精進之路之第13篇-生命周期·進階】省略規則與靜態生命周期 (`‘static`)

系列: Rust 精進之路:構建可靠、高效軟件的底層邏輯 作者: 碼覺客 發布日期: 2025年4月20日 引言:讓編譯器“讀懂”你的意圖——省略的藝術 在上一篇【生命周期入門】中,我們理解了生命周期的必要性——它是 Rust 編譯器用來確保引用有效性、防止懸垂引用的關鍵機制。我…

Python爬蟲實戰:獲取xie程網敦煌酒店數據并分析,為51出行做參考

一、引言 伴隨互聯網的飛速發展,在線旅游平臺成為人們出行預訂酒店的重要途徑。xie程網作為國內頗具知名度的在線旅游平臺,存有豐富的酒店信息。借助爬取xie程網的酒店數據并加以深入分析,能夠為用戶提供更為精準的酒店推薦,特別是在旅游旺季,如 51 出行期間。本研究致力…

第二十一講 XGBoost 回歸建模 + SHAP 可解釋性分析(利用R語言內置數據集)

下面我將使用 R 語言內置的 mtcars 數據集&#xff0c;模擬一個完整的 XGBoost 回歸建模 SHAP 可解釋性分析 實戰流程。我們將以預測汽車的油耗&#xff08;mpg&#xff09;為目標變量&#xff0c;構建 XGBoost 模型&#xff0c;并用 SHAP 來解釋模型輸出。 &#x1f697; 示例…

PyMC+AI提示詞貝葉斯項目反應IRT理論Rasch分析籃球比賽官方數據:球員能力與位置層級結構研究

全文鏈接&#xff1a;tecdat.cn/?p41666 在體育數據分析領域不斷發展的當下&#xff0c;數據科學家們致力于挖掘數據背后的深層價值&#xff0c;為各行業提供更具洞察力的決策依據。近期&#xff0c;我們團隊完成了一項極具意義的咨詢項目&#xff0c;旨在通過先進的數據分析手…

【android bluetooth 框架分析 03】【Bta 層詳解 1】【Bluetooth Application Laye 介紹】

藍牙協議棧中 Bluetooth Application Layer&#xff08;藍牙應用層&#xff09;是協議棧核心組成部分&#xff0c;它位于協議棧中間偏上的位置&#xff0c;主要負責將底層 Bluetooth Stack&#xff08;如 L2CAP、AVDTP、RFCOMM、SDP 等&#xff09;與上層 Profile 和 Android F…

單片機獲取真實時間的實現方法

單片機獲取真實時間&#xff08;即當前的年月日、時分秒等&#xff09;通常需要依賴外部時間源或模塊&#xff0c;因為單片機本身沒有內置的實時時鐘&#xff08;RTC&#xff09;功能。 在 C 語言環境下&#xff0c;單片機獲取真實時間通常需要依賴 外部硬件模塊&#xff08;如…

Linux——進程優先級/切換/調度

1.進程優先級 1.進程優先級是什么&#xff1a;進程獲取CPU資源的先后順序 2.為什么要有進程優先級&#xff1a;因為一般CPU只有一塊&#xff0c;資源短缺&#xff0c;所以就需要優先級來確定誰先誰后的問題 3.值越低 進程的優先級越高 ps -l進行查看 UID&#xff1a;user id …

鑄鐵劃線平板:多行業的精密測量工具(北重十字滑臺加工廠家)

鑄鐵劃線平板是一種用于精密測量和校準的工具&#xff0c;廣泛應用于各個行業。它通常由鑄鐵制成&#xff0c;表面經過精密加工&#xff0c;能夠保證較高的平整度和準確度。鑄鐵劃線平板的主要作用是用來檢驗工件的平整度和垂直度&#xff0c;也常用于劃線、校準和測量工件的平…

Excel/WPS表格中圖片鏈接轉換成對應的實際圖片

Excel 超鏈圖變助手&#xff08;點擊下載可免費試用&#xff09; 是一款將鏈接轉換成實際圖片&#xff0c;批量下載表格中所有圖片的轉換工具&#xff0c;無需安裝&#xff0c;雙擊打開即可使用。 表格中鏈接如下圖所示&#xff1a; 操作方法&#xff1a; 1、雙擊以下圖標&a…

STM32---串口通信USART

目錄 一、串口通信協議 二、USART模塊介紹 &#xff08;1&#xff09;移位寄存器 &#xff08;2&#xff09;控制電路 &#xff08;3&#xff09;波特率 &#xff08;4&#xff09;C語言接口 三、串口的引腳初始化 &#xff08;1&#xff09;引腳分布表 &…

流程架構是什么?為什么要構建流程架構,以及如何構建流程結構?

本文從&#xff1a;流程架構是什么&#xff1f;為什么要構建流程架構&#xff1f;如何構建流程結構三個方面來介紹。 一、首先&#xff0c;我們來了解流程架構是什么&#xff1f; 流程架構是人體的骨架&#xff0c;是大樓的砌筑&#xff0c;是課本的目錄&#xff0c;是流程管理…

網絡結構及安全科普

文章目錄 終端聯網網絡硬件基礎網絡協議示例&#xff1a;用戶訪問網頁 OSI七層模型網絡攻擊&#xff08;Hack&#xff09;網絡攻擊的主要類別&#xff08;一&#xff09;按攻擊目標分類&#xff08;二&#xff09;按攻擊技術分類 網絡安全防御 典型攻擊案例相關名詞介紹網絡連接…

同z科技面經

同z科技-2025-4-23 1.自我介紹 個人信息 校園經歷 實習經歷 項目經歷 個人技能掌握 目前學習技術 2.封裝緩存工具類怎么封裝的 先介紹使用緩存的問題 解決的邏輯 封裝的邏輯 應用 緩存穿透&#xff1a; 緩存雪崩&#xff1a; 緩存擊穿&#xff1a; https://www…

基于LoRA的Llama 2二次預訓練實踐:高效低成本的大模型領域適配

引言 近年來&#xff0c;大語言模型&#xff08;LLM&#xff09;如Meta的Llama 2系列憑借其強大的生成和理解能力成為NLP領域的核心工具。然而&#xff0c;直接將通用預訓練模型應用于垂直領域&#xff08;如醫療、法律、金融&#xff09;時&#xff0c;常面臨領域知識不足的問…

Python爬蟲(2)Python爬蟲入門:從HTTP協議解析到豆瓣電影數據抓取實戰

目錄 一、背景與需求?二、 Web基礎與HTTP協議核心解析?2.1 HTTP協議&#xff1a;數據交互的基石?2.2 為何爬蟲需理解HTTP協議&#xff1f;? 三、 Python爬蟲實戰&#xff1a;Requests庫核心用法?3.1 安裝與環境配置?3.2 案例1&#xff1a;GET請求抓取豆瓣電影Top250?3.3…

深度學習--ResNet殘差神經網絡解析

文章目錄 前言一、什么是ResNet網絡二、傳統卷積神經網絡存在的問題1、梯度消失和梯度爆炸2、退化問題 三、如何解決問題四、殘差結構五、18層殘差網絡1、解釋2、隔層相加優點3、隔層相加數值增大問題 六、18層殘差網絡以外的表格示例七、BN層&#xff08;Batch Normalization&…

【go】go run-gcflags常用參數歸納,go逃逸分析執行語句,go返回局部變量指針是安全的

go官方參考文檔&#xff1a; https://pkg.go.dev/cmd/compile 基本語法 go run 命令用來編譯并運行Go程序&#xff0c;-gcflags 后面可以跟一系列的編譯選項&#xff0c;多個選項之間用空格分隔。基本語法如下&#xff1a; go run -gcflags "<flags>" main.…

K8S探針的應用

目錄&#xff1a; 1、探針的簡介2、啟用探針2.1、啟用就緒探針2.2、啟用存活探針2.3、啟用啟動探針&#xff08;可選&#xff09; 1、探針的簡介 在Kubernetes中&#xff0c;探針&#xff08;Probes&#xff09;是用來檢查容器健康狀況的工具&#xff0c;它們幫助Kubernetes了…