RabbitMQ--@RabbitListener及@RabbitHandle

兩者區別? ? ?

???在?Spring AMQP?中,@RabbitListener?和?@RabbitHandler?是處理 RabbitMQ 消息的核心注解,但職責和使用場景完全不同。以下從?定義、區別、場景、示例?逐層解析:

一、核心定義

1.?@RabbitListener

  • 作用:標記?方法或類?為?RabbitMQ 消息監聽器,負責綁定隊列、啟動消息監聽。
  • 能力
    • 可直接聲明隊列、交換機、綁定關系(通過?@QueueBinding)。
    • 啟動后,持續監聽隊列,接收消息并處理。

2.?@RabbitHandler

  • 作用:在?@RabbitListener?標記的類中,根據?消息 payload 的類型,將消息分發給對應的方法。
  • 能力:實現?同一隊列內多種消息類型的差異化處理(類似 Java 的方法重載)。

二、關鍵區別

維度@RabbitListener@RabbitHandler
標記位置方法??類(類需是 Spring 組件,如?@Component只能標記方法,且必須在?@RabbitListener?標記的類中
核心職責綁定隊列、啟動監聽,定義 “監聽哪個隊列”根據消息類型,分發到具體方法,定義 “如何處理該類型消息”
依賴關系可獨立使用(方法級);類級使用時需配合?@RabbitHandler必須依賴?@RabbitListener(類級),無法單獨使用
消息綁定通過?@QueueBinding?聲明隊列、交換機、路由鍵不涉及隊列綁定,只負責類型匹配

三、使用場景對比

1.?@RabbitListener?單獨使用(方法級)

  • 場景:隊列中的?消息類型單一(如只有?String?或單一對象),一個方法即可處理。
  • 示例
    @Component
    public class SimpleListener {// 直接監聽 "simple_queue",處理 String 類型消息@RabbitListener(queues = "simple_queue")public void handleString(String message) {System.out.println("收到字符串消息: " + message);}
    }
    

2.?@RabbitListener(類級) +?@RabbitHandler(多方法)

  • 場景:隊列中的?消息類型多樣(如同時有?StringUserOrder?等),需不同方法處理。
  • 示例
    @Component
    @RabbitListener(queues = "mixed_queue") // 監聽混合類型消息的隊列
    public class MixedListener {// 處理 String 類型消息@RabbitHandlerpublic void handleString(String message) {System.out.println("字符串消息: " + message);}// 處理 User 類型消息(需保證生產者發送的是 User 對象,且序列化正確)@RabbitHandlerpublic void handleUser(User user) {System.out.println("用戶消息: " + user.getName());}// 處理 Order 類型消息@RabbitHandlerpublic void handleOrder(Order order) {System.out.println("訂單消息: " + order.getOrderId());}
    }
    

3. 高級用法:@QueueBinding?與?@RabbitListener?結合

  • 場景:監聽隊列時,需?動態聲明隊列、交換機、綁定關系(無需手動在 RabbitMQ 管理界面創建)。
  • 示例(Direct 交換機 + 路由鍵綁定):

    java

    @Component
    public class DirectListener {// 聲明隊列、交換機、綁定關系,同時監聽消息@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct_queue", durable = "true"),exchange = @Exchange(name = "direct_exchange", type = ExchangeTypes.DIRECT),key = "direct_key" // 路由鍵))public void handleDirectMessage(String message) {System.out.println("Direct 消息: " + message);}
    }
    

四、底層原理:為什么需要兩者配合?

  • @RabbitListener?負責?“連接 MQ 并訂閱隊列”,是消息監聽的入口。
  • @RabbitHandler?負責?“消息類型分發”,解決 “同一隊列內多種消息類型如何差異化處理” 的問題。

類比:@RabbitListener?是 “快遞站”(訂閱隊列,接收包裹),@RabbitHandler?是 “分揀員”(根據包裹內容,分給不同的處理人員)。

五、避坑指南

  1. @RabbitHandler?只在類級?@RabbitListener?中生效

    • 如果?@RabbitListener?標記方法,@RabbitHandler?會被忽略。
  2. 消息類型必須匹配

    • 生產者發送的消息需正確序列化(如 JSON),消費者才能反序列化為?@RabbitHandler?方法的參數類型。
    • 若類型不匹配,會拋出?AmqpException(如 “找不到匹配的?@RabbitHandler?方法”)。
  3. 類級?@RabbitListener?需是 Spring 組件

    • 標記?@Component@Service?等,確保 Spring 掃描并創建 Bean,否則監聽不生效。

總結:如何選擇?

  • 簡單場景(單一消息類型):直接用?方法級?@RabbitListener,無需?@RabbitHandler
  • 復雜場景(多消息類型):用?類級?@RabbitListener?+ 多個?@RabbitHandler,按類型分發處理。
  • 需動態聲明隊列 / 交換機:結合?@QueueBinding?和?@RabbitListener(方法級或類級均可)。

那要是綁定不同的消息隊列呢?

? ? ? ? 以Fanout交換機為例

先看代碼的核心邏輯:每個?@RabbitListener?都綁定了獨立的臨時隊列?

Fanout 交換機的廣播特性?

?示例中,兩個?@RabbitListener?的結構如下(簡化分析):

@Component
public class FanoutCustomer {// 🔵 消費者1:綁定臨時隊列A → 交換機logs(Fanout)@RabbitListener(bindings = @QueueBinding(value = @Queue, // 臨時隊列A(無名稱,自動生成)exchange = @Exchange(value = "logs", type = "fanout")))public void receive1(String message) { ... }// 🔵 消費者2:綁定臨時隊列B → 交換機logs(Fanout)@RabbitListener(bindings = @QueueBinding(value = @Queue, // 臨時隊列B(無名稱,自動生成,與A不同)exchange = @Exchange(value = "logs", type = "fanout")))public void receive2(String message) { ... }
}

二、關鍵機制:每個?@RabbitListener?都會創建獨立的隊列

  • @Queue?無名稱 → 臨時隊列
    Spring AMQP 會為每個?@Queue(無名稱)生成?唯一的臨時隊列(如?amq.gen-xxx),連接關閉時自動刪除。
  • 每個?@RabbitListener?綁定自己的隊列
    receive1?綁定?臨時隊列 Areceive2?綁定?臨時隊列 B,兩個隊列相互獨立。

三、Fanout 交換機的廣播特性:兩個隊列都會收到消息

Fanout 交換機的核心是?“廣播消息到所有綁定的隊列”

  • 當生產者向?logs?交換機發消息時,臨時隊列 A 和 B 都會收到相同的消息
  • 因此,receive1?和?receive2?都會被觸發,各自處理自己隊列里的消息(內容相同,但屬于不同隊列的消費)。

四、為什么不用?@RabbitHandler?(對比場景)

以?Fanout 交換機的廣播

? ?@RabbitHandler?的核心是?“同一隊列內的消息類型分發”,而示例的場景是?“多隊列的廣播消費”,兩者適用場景完全不同:

場景 1:多隊列廣播(示例中的用法)

  • 需求:讓?多個消費者(隊列)都收到消息(如日志系統,多個消費者分別記錄日志、推送通知)。
  • 實現:每個消費者用?@RabbitListener?綁定獨立隊列(臨時隊列),借助 Fanout 交換機的廣播特性,讓所有隊列都收到消息。

場景 2:同一隊列的多類型消息(需用?@RabbitHandler

  • 需求:同一隊列里有?不同類型的消息(如?StringUserOrder),需分發給不同方法處理。
  • 實現
    @Component
    @RabbitListener(queues = "mixed_queue") // 監聽同一個隊列
    public class MixedListener {// 處理 String 類型@RabbitHandlerpublic void handleString(String msg) { ... }// 處理 User 類型@RabbitHandlerpublic void handleUser(User user) { ... }
    }
    

五、總結:兩個?@RabbitListener?的設計意圖

Fanout 交換機的廣播特性?

? ?示例中,兩個?@RabbitListener?并非 “處理不同消息類型”,而是?“模擬兩個獨立的消費者,同時接收 Fanout 交換機的廣播消息”

  • 每個?@RabbitListener?對應一個?獨立的臨時隊列,都綁定到 Fanout 交換機。
  • Fanout 交換機將消息廣播到兩個隊列,因此?receive1?和?receive2?都會被調用,實現 “同一消息被多個消費者處理” 的效果(如日志既存文件又推送到前端)。

擴展思考:如果要讓同一隊列支持多類型消息,如何改造?

只需將兩個?@RabbitListener?改為?類級?@RabbitListener?+?@RabbitHandler

@Component
@RabbitListener(bindings = @QueueBinding(value = @Queue, // 單個臨時隊列exchange = @Exchange(value = "logs", type = "fanout")
))
public class FanoutCustomer {// 處理 String 消息@RabbitHandlerpublic void receive1(String message) { ... }// 處理 User 消息(假設生產者發 User 對象)@RabbitHandlerpublic void receive2(User user) { ... }
}

此時,同一個臨時隊列?接收 Fanout 廣播的消息,@RabbitHandler?根據消息類型(String?或?User)分發到不同方法。

理解這一點后,就能區分:

  • 多隊列廣播?→ 多個?@RabbitListener(每個綁定獨立隊列)。
  • 同一隊列多類型?→ 類級?@RabbitListener?+ 多個?@RabbitHandler

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

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

相關文章

【基于CKF的IMM】MATLAB例程,CV和CT兩個模型下的IMM,二維,濾波使用CKF(容積卡爾曼濾波),附下載鏈接

本程序實現了基于交互多模型(IMM)容積卡爾曼濾波(CKF)的多模型融合定位方法,并與純CV?CKFCV-CKFCV?CKF(勻速模型)和CT?CKFCT-CKFCT?CKF(勻角速度轉彎模型)方法對比。…

AI資訊日報 - 2025年07月28日

AI資訊日報 | 2025年07月28日 周一 今日核心要點 精華提煉 技術突破 ? 騰訊混元:開源發布、3D技術 ? 書生Intern:開源發布、多模態 企業動態 ? AI工具集:協同創作、視頻生成 數據概覽分類數量重點關注技術突破2 條開源發布、3D技術企業動態…

大語言模型 LLM 通過 Excel 知識庫 增強日志分析,根因分析能力的技術方案(1):總體介紹

文章大綱 1. 核心目標 2. 系統總體架構 3. Google Cloud 端到端方案(含無 RAG & RAG 雙模式) 3.1 無 RAG:Function-Calling 查表模式 3.2 RAG:托管式向量檢索 4. 開源輕量級方案 5. 數字孿生聯合驗證(實驗性) 6. 知識圖譜增強(Neo4j) 7. 監控與持續優化(CometLLM)…

Deepseek + browser-use 輕松實現瀏覽器自動化

在數字化時代,瀏覽器應用廣泛,瀏覽器自動化可大幅提升效率。Deepseek 是強大的智能語言模型,能精準解析復雜指令,browser - use 是專注瀏覽器操作的工具,提供豐富 API 接口,支持主流瀏覽器的各類自動化操作…

開疆智能ModbusTCP轉Profient網關連接西門子PLC與川崎機器人配置案例

本案例是西門子PLC與川崎機器人通過Profient轉ModbusTCP網關進行通訊轉換的配置案例,西門子作為profinet主站,機器人作為ModbusTCP服務器。配置過程:機器人配置川崎機器人控制器提供了RS232、以太網的通信接口,同時也可通過加裝選…

Docker多主機網絡連接:實現跨主機通信

Docker 是一種流行的容器化平臺,它可以幫助開發人員更方便地構建、發布和管理應用程序。在 Docker 中,容器是獨立運行的應用程序包裝,包含了運行所需的所有文件、庫和環境變量。Docker 提供了多種網絡連接方式,使得容器之間可以進…

OSPF筆記

一、OSPF基礎1、技術背景(RIP中存在的問題)RIP中存在最大跳數為15的限制,不能適應大規模組網周期性發送全部路由信息,占用大量的帶寬資源路由收斂速度慢以跳數作為度量值存在路由環路可能性每隔30秒更新2、OSPF協議特點沒有跳數限…

kotlin基礎【3】

Kotlin Playground: Edit, Run, Share Kotlin Code Online 資料&#xff1a;kotlin實戰 第一章 data class Person(val name: String,val age:Int?null)//允許接受以age為空&#xff0c;當為空將它賦值為null,如果不這么寫直接寫age:Int?是否可以fun main(args:Array<St…

Java-數構二叉樹

1.樹 1.1概念 樹是一種非線性的數據結構&#xff0c;它是由n個有限節點組成一個具有層次關系。這種結構有以下特點&#xff1a; 一個特殊的結點&#xff0c;稱為根節點&#xff0c;根節點沒有前驅節點除根節點以外&#xff0c;其余節點分成M個互不相交的集合。每個集合又是一…

編程中水合的理解

在編程中&#xff0c;水合&#xff08;Hydration&#xff09; 是一個常見概念&#xff0c;尤其在 前端開發 和 服務端渲染&#xff08;SSR&#xff09; 場景中頻繁出現。它的核心含義是&#xff1a;將靜態內容“激活”為交互式動態內容。1. 水合的本質簡單理解&#xff1a;水合…

使用ffmpeg轉碼h265后mac默認播放器不支持問題

由于mac自帶錄屏是mov并且文件特別大&#xff0c;我使用ffmpeg轉碼視頻為h265使用如下命令ffmpeg_command [ffmpeg_path,"-i", input_path,"-c:v", "libx265","-preset", "veryslow","-map_metadata", "0&q…

支持MySQL、PostgreSQL和Redis集群部署,1Panel開源面板v2.0.5版本發布

2025年7月24日&#xff0c;現代化、開源的Linux服務器運維管理面板1Panel正式發布v2.0.5版本。在這一版本中&#xff0c;1Panel新增數據庫集群部署、郵件告警和主從節點靈活切換三項功能&#xff0c;聚焦為企業級運維場景提供更優使用體驗。 1Panel v2.0.5版本是1Panel開源面板…

GaussDB 數據庫架構師修煉(九) 邏輯備份實操

1 邏輯備份定義 邏輯備份是指與業務有關的對象進行備份&#xff0c;這個對象包括表、表的數據、視圖、索引、過程、函數等等。GaussDB支持邏輯備份的工具為gs_dump、gs_restore&#xff0c;以下舉例說明。 2 創建舉例數據 以下創建testdb庫&#xff0c;創建test1模式&#xf…

c# Winform發布成獨立文件

改造前&#xff1a; 通過發布頁面&#xff0c;修改部署模式為獨立&#xff0c;輸出文件目錄沒有完全包含所有dll改造后&#xff1a;通過修改項目文件方式修改csproj前&#xff1a;<PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net…

Android基礎(一) 運行HelloWorld

Android基礎&#xff08;一&#xff09; 運行HelloWorld一、創建你的第一個Android項目二、創建HelloWorld項目三、安裝并啟動模擬器四、安裝三方模擬器五、使用真機一、創建你的第一個Android項目 學習任何一門編程語言&#xff0c;編寫的第一個程序都是Hello World&#xff0…

MongoDB 和 Elasticsearch(ES)區別

MongoDB 和 Elasticsearch&#xff08;ES&#xff09;都是流行的 NoSQL 數據庫&#xff0c;但設計目標和適用場景有顯著區別。以下是它們的核心差異和典型使用場景對比&#xff1a;1. 核心定位特性MongoDBElasticsearch數據庫類型文檔數據庫&#xff08;通用型 OLTP&#xff09…

【C++算法】89.多源BFS_01 矩陣

文章目錄題目鏈接&#xff1a;題目描述&#xff1a;解法C 算法代碼&#xff1a;題目鏈接&#xff1a; 542. 01 矩陣 題目描述&#xff1a; 解法 先看懂題目 解法一&#xff1a;一個位置一個位置求&#xff08;最差的情況下會非常恐怖&#xff09; 解法二&#xff1a;多源BFS正…

數據結構之 【排序】(歸并排序)

目錄 1.遞歸實現歸并排序的思想及圖解 2.遞歸實現歸并排序的代碼邏輯 2.1嵌套子函數 2.2遞歸過程 2.3遞歸結束條件 2.4歸并及拷貝過程 3.非遞歸實現歸并排序的思想及圖解 4.非遞歸實現歸并排序的代碼邏輯 4.1邊歸并邊拷貝 4.2某一gap下歸并完成才進行拷貝 5.歸并排…

企業如何選擇適合的高防服務器?

高防服務器租用哪家好&#xff1f;這個問題困擾著許多站長&#xff0c;建立的網站經常受到各種網絡攻擊&#xff0c;雖然高防服務器有著較高的防御性能&#xff0c;十分適合經常被攻擊的行業網站&#xff0c;但是如何租到滿意的高防服務器呢&#xff01;徐州高防服務器是部署在…

告別重復勞動:Ansible 自動化運維超詳細學習路線圖

在運維的世界里&#xff0c;我們總是在與重復性任務作斗爭&#xff1a;部署同一套環境 N 次、在幾十臺服務器上修改同一個配置文件、一遍又一遍地執行相同的發布流程……這些工作不僅枯燥&#xff0c;還極易出錯。 如果你也為此感到煩惱&#xff0c;那么 Ansible 就是為你量身打…