【RabbitMQ】基于Spring Boot + RabbitMQ 完成應用通信

文章目錄

  • 需求描述
  • 創建項目
  • 訂單系統(生產者)
    • 完善配置
    • 聲明隊列
    • 下單接口
    • 啟動服務
  • 物流系統(消費者)
    • 完善配置
    • 監聽隊列
    • 啟動服務
  • 格式化發送消息對象
    • SimpleMessageConverter
      • 定義一個對象
      • 生產者代碼
      • 消費者
      • 運行程序
    • JSON
      • 定義一個對象
      • 生產者代碼
      • 定義轉換器
      • 消費者代碼
      • 運行程序

需求描述

用戶下單成功之后,通知物流系統,進行發貨(只涉及到應用通信,不做具體功能實現)
image.png

  • 訂單系統——生產者
  • 物流系統——消費者

創建項目

通常情況下,訂單系統和物流系統是不同團隊來開發的,是兩個獨立的應用

  • 為了方便演示,就把兩個項目創建到一個文件夾下

image.png|291

  • 圖標沒有發生變化,啟動類也沒有被識別出來
    • 因為 Maven 沒有被識別出來
    • 我們手動加入 Maven
      • 在項目目錄中右鍵點擊 pom.xml 文件,選擇:Add as Maven Projectimage.png|191

訂單系統(生產者)

完善配置

image.png

spring.application.name=order-service
server.port=8080  
#amqp://username:password@Ip:port/virtual-host  
spring.rabbitmq.addresses=amqp://order:order@127.0.0.1:5672/order

聲明隊列

package org.example.order.config;  import org.springframework.amqp.core.Queue;  
import org.springframework.amqp.core.QueueBuilder;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  @Configuration  
public class RabbitMQConfig {  // 使用簡單模式來完成消息發送  @Bean  public Queue orderQueue(){  return QueueBuilder.durable("order.create").build();  }  
}

下單接口

package org.example.order.controller;  import org.springframework.amqp.rabbit.core.RabbitTemplate;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  import java.util.UUID;  @RequestMapping("/order")  
@RestController  
public class OrderController {  // 注入RabbitMQ的客戶端  @Autowired  private RabbitTemplate rabbitTemplate;  // 下單的接口  @RequestMapping("/create")  public String create(){  // 參數校驗、數據庫保存等等...業務代碼省略  // 發送消息  // 交換機、隊列是什么routingKey就是什么、字符串信息  String orderId = UUID.randomUUID().toString();  rabbitTemplate.convertAndSend("", "order.create", "訂單信息,訂單ID: " + orderId);  return "下單成功";  }  
}
  • 下單成功之后,發送訂單消息

啟動服務

  1. 訪問接口,模擬下單請求: http://127.0.0.1:8080/order/create

查看消息:image.png

物流系統(消費者)

RabbitMQ 中接收消息

完善配置

8080 端口號已經被訂單系統占用了,修改物流系統的端口號為 9090

spring.application.name=logistics-service  
# 兩邊的端口號不能一樣,他們是同時運行的  
server.port=9090  
#amqp://username:password@Ip:port/virtual-host  
spring.rabbitmq.addresses=amqp://guest:guest@127.0.0.1:5672/order

監聽隊列

package org.example.logistics.listener;  import org.springframework.amqp.rabbit.annotation.RabbitListener;  
import org.springframework.stereotype.Component;  @Component  
public class OrderListener {  @RabbitListener(queues = "order.create") // 指出需要監聽的隊列的名稱  public void handMessage(String orderInfo) {  System.out.println("接收到訂單消息: " + orderInfo);  // 收到消息后的處理,代碼省略}  
}

啟動服務

訪問訂單系統的接口,模擬下單請求: http://127.0.0.1:8080/order/create

在物流系統的日志中,可以觀察到,通過 RabbitMQ,成功把下單信息傳遞給了物流系統image.png

格式化發送消息對象

如果通過 RabbitTemplate 發送?個對象作為消息, 我們需要對該對象進?序列化

SimpleMessageConverter

默認使用的是 SimpleMessageConverter 進行序列化

定義一個對象

package org.example.order.model;  import lombok.Data;  import java.io.Serializable;  @Data  
public class OrderInfo implements Serializable {  private String orderId;  private String name;  
}
  • 在發送消息的時候,信息需要經過 MessageConverter 進行轉換 (默認是 SimpleMessageConverter)
  • SimpleMessageConverter 只支持 Stringbyte[]Serializable
  • 此接口將 OrderInfo 序列化,之后才能被正常接收 (OrderInfo 類型不被支持,會報 500 錯誤)

生產者代碼

package org.example.order.controller;  import org.example.order.model.OrderInfo;  
import org.springframework.amqp.rabbit.core.RabbitTemplate;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  import java.util.Random;  
import java.util.UUID;  @RequestMapping("/order")  
@RestController  
public class OrderController {  // 注入RabbitMQ的客戶端  @Autowired  private RabbitTemplate rabbitTemplate;  // 下單的接口  @RequestMapping("/create2")  public String create2(){  // 發送對象  OrderInfo orderInfo = new OrderInfo();  orderInfo.setOrderId(UUID.randomUUID().toString());  orderInfo.setName("商品" + new Random().nextInt(100));  rabbitTemplate.convertAndSend("", "order.create", orderInfo);  return "下單成功";  }  
}

消費者

package org.example.logistics.listener;  import org.example.order.model.OrderInfo;  
import org.springframework.amqp.rabbit.annotation.RabbitHandler;  
import org.springframework.amqp.rabbit.annotation.RabbitListener;  
import org.springframework.stereotype.Component;  @Component  
@RabbitListener(queues = "order.create") // 指出需要監聽的隊列的名稱  
public class OrderListener {  @RabbitHandler  public void handMessage(String orderInfo) {  System.out.println("接收到訂單消息String: " + orderInfo);  // 收到消息后的處理,代碼省略  }  
}

運行程序

訪問訂單系統的接口,模擬下單請求: http://127.0.0.1:8080/order/create2

觀察發送的消息image.png

  • 可以看到消息的可讀性太差
  • 所以我們使用 JSON 序列化

JSON

使用 SimpleMessageConverter 序列化可讀性太差,Spring AMQP 推薦使用 JSON 序列化

  • Spring AMQP 提供了 Jsckson2JsonMessageConverterMappingJackson2MessageConverter 等轉換器
  • 我們需要把一個 MessageConverter 設置到 RabbitTemplate

定義一個對象

package org.example.order.model;  import lombok.Data;  @Data  
public class OrderInfo  {  private String orderId;  private String name;  
}

生產者代碼

package org.example.order.controller;  import org.example.order.model.OrderInfo;  
import org.springframework.amqp.rabbit.core.RabbitTemplate;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  import java.util.Random;  
import java.util.UUID;  @RequestMapping("/order")  
@RestController  
public class OrderController {  // 注入RabbitMQ的客戶端  @Autowired  private RabbitTemplate rabbitTemplate;  // 下單的接口  @RequestMapping("/create2")  public String create2(){  // 發送對象  OrderInfo orderInfo = new OrderInfo();  orderInfo.setOrderId(UUID.randomUUID().toString());  orderInfo.setName("商品" + new Random().nextInt(100));  rabbitTemplate.convertAndSend("", "order.create", orderInfo);  return "下單成功";  }  
}
  • 和前面的使用默認轉換器代碼一樣

定義轉換器

package org.example.order.config;  import org.springframework.amqp.core.Queue;  
import org.springframework.amqp.core.QueueBuilder;  
import org.springframework.amqp.rabbit.connection.ConnectionFactory;  
import org.springframework.amqp.rabbit.core.RabbitTemplate;  
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  @Configuration  
public class RabbitMQConfig {  // 使用簡單模式來完成消息發送  @Bean  public Queue orderQueue(){  return QueueBuilder.durable("order.create").build();  }  /**  * 創建一個 rabbitTemplate 對象  * @return  */  @Bean  public Jackson2JsonMessageConverter jsonMessageConverter(){  return new Jackson2JsonMessageConverter();  }  @Bean  public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, Jackson2JsonMessageConverter jsonMessageConverter) {  RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);  rabbitTemplate.setMessageConverter(jsonMessageConverter);  return rabbitTemplate;  }  
}
  • 創建出一個 rabbitTemplate 對象進行使用
  • 生產者(order-service)和消費者(logistics-service)都需要
    • 不然還是拿不到消息

消費者代碼

package org.example.logistics.listener;  import org.example.order.model.OrderInfo;  
import org.springframework.amqp.rabbit.annotation.RabbitHandler;  
import org.springframework.amqp.rabbit.annotation.RabbitListener;  
import org.springframework.stereotype.Component;  @Component  
@RabbitListener(queues = "order.create") // 指出需要監聽的隊列的名稱  
public class OrderListener {  @RabbitHandler  public void handMessage2(OrderInfo orderInfo) {  System.out.println("接收到訂單消息OrderInfo: " + orderInfo);  // 收到消息后的處理,代碼省略  }  
}

@RabbitListener(queues = "order.create") 可以加在類上,也可以加在方法上,用于定義一個類或者方法作為消息的監聽器
@RabbitHandler 是一個方法級別的注解,當使用 @RabbitHandler 注解時,這個方法將被調用處理特定的消息

  • 根據調用的類型,調用相關方法

運行程序

訪問訂單系統的接口,模擬下單請求: http://127.0.0.1:8080/order/create2

image.png

前面的 String 也還可以接收到,只要模擬下單請求: http://127.0.0.1:8080/order/create 即可image.png

  • 歸功于 @RabbitHandler指哪打哪

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

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

相關文章

OpenGL Chan視頻學習-7 Writing a Shader inOpenGL

bilibili視頻鏈接: 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函數網站: docs.gl 說明: 1.之后就不再整理具體函數了,網站直接翻譯會更直觀也會…

Vue 3.0中復雜狀態如何管理

在現代前端應用中,狀態管理扮演著至關重要的角色。一個良好的狀態管理方案能夠: 1. 保持應用數據的一致性和可預測性; 2. 簡化組件間的通信和數據共享; 3. 提高代碼的可維護性和可測試性; 4. 優化應用性能&#xf…

AGI大模型(33):LangChain之Memory

大多數的 LLM 應用程序都會有一個會話接口,允許我們和 LLM 進行多輪的對話,并有一定的上下文記憶能力。但實際上,模型本身是不會記憶任何上下文的,只能依靠用戶本身的輸入去產生輸出。而實現這個記憶功能,就需要額外的模塊去保存我們和模型對話的上下文信息,然后在下一次…

leetcode513. 找樹左下角的值:層序遍歷中的深度與順序控制之道

一、題目深度解析與核心訴求 在二叉樹的眾多問題中,尋找最深層最左節點的值是一個兼具趣味性與代表性的問題。題目要求我們在給定的二叉樹中,找到深度最大的那一層中最左邊的節點值。如果存在多個最深層,只需返回最左邊節點的值即可。 這個…

制作一款打飛機游戲54:子彈編輯UI

今天,我們將繼續工作在我們的子彈模式系統上,創建一些簡單的子彈,并為其設計用戶界面(UI)。 自動保存功能的重要性 首先,我想提一下自動保存功能。這個功能在編輯器中非常重要,因為我們經常犯…

線程封裝與互斥

目錄 線程互斥 進程線程間的互斥相關背景概念 互斥量mutex 互斥量的接口 初始化互斥量有兩種方法: 銷毀互斥量 互斥量加鎖和解鎖 改進售票系統 互斥量實現原理探究 互斥量的封裝 線程互斥 進程線程間的互斥相關背景概念 臨界資源:多線程執行流共…

【系統設計】2WTPS生產級數據處理系統設計Review

歡迎來到啾啾的博客🐱。 記錄學習點滴。分享工作思考和實用技巧,偶爾也分享一些雜談💬。 有很多很多不足的地方,歡迎評論交流,感謝您的閱讀與評論😄。 目錄 反正能用的系統問題分析方案一:簡單多…

歷年北京理工大學保研上機真題

2025北京理工大學保研上機真題 2024北京理工大學保研上機真題 2023北京理工大學保研上機真題 在線測評鏈接:https://pgcode.cn/problem?classification1 判斷身份證校驗位是否正確 題目描述 給定一個身份證號碼,判斷其最后一位校驗位是否正確。 如果…

uni-app學習筆記十--vu3綜合練習

鞏固提升前面學習的知識點,主要涉及下面這方面的運用: 1.v-for運用; 2.v-model雙向綁定; 3.confirm確認事件; 4.click點擊事件; 5.控制按鈕的可點擊和不可點擊; 6.集合刪除和追加元素,獲取集合元素的…

AI時代新詞-AI芯片(AI - Specific Chip)

一、什么是AI芯片? AI芯片(AI - Specific Chip)是指專為人工智能(AI)計算任務設計的芯片。與傳統的通用處理器(如CPU)相比,AI芯片針對深度學習、機器學習等AI應用進行了優化&#x…

華為云Astro前端頁面數據模型選型及綁定IoTDA物聯網數據實施指南

目錄 1. 選擇合適的數據模型類型及推薦理由 自定義模型: 對象模型: 服務模型: 事件模型: 推薦方案: 2. 數據模型之間的邏輯關系說明 服務模型獲取數據: 對象模型承接數據: 前端組件綁定顯示: 數據保存與反饋(可選): (可選)事件模型實時更新: 小結 …

因重新安裝python新版本,pycharm提示找不到python.exe(No Python at“c:\python.exe“)問題解決方法

1、安裝新版本python后提示錯誤如下: 2、打開設置 3、添加Interpreter 4、配置程序的安裝路徑 5、問題完美解決。

一文帶你徹底理清C 語言核心知識 與 面試高頻考點:從棧溢出到指針 全面解析 附帶筆者手寫2.4k行代碼加注釋

引言:C 語言的魅力與挑戰 從操作系統內核到嵌入式系統,從高性能計算到網絡編程,C 語言高效、靈活和貼近硬件的特性,始終占據著不可替代的地位。然而,C 語言的強大也伴隨著較高的學習曲線,尤其是指針、內存管…

GitHub 趨勢日報 (2025年05月22日)

本日報由 TrendForge 系統生成 https://trendforge.devlive.org/ 🌐 本日報中的項目描述已自動翻譯為中文 📈 今日整體趨勢 Top 10 排名項目名稱項目描述今日獲星總星數語言1microsoft/WSLLinux的Windows子系統? 2524? 26627C2HeyPuter/puter&#x1…

AI智能混剪核心技術解析(一):字幕與標題生成的三大支柱-字幕與標題生成-優雅草卓伊凡

AI智能混剪核心技術解析(一):字幕與標題生成的三大支柱-字幕與標題生成-優雅草卓伊凡 引言:文字到畫面的橋梁工程 在AI視頻混剪系統中,字幕與標題生成是連接語言表達與視覺呈現的核心樞紐。優雅草卓伊凡團隊將該功能拆…

如何通過PHPMyadmin對MYSQL數據庫進行管理?

管理MySQL數據庫時,使用PHPMyAdmin是一種常見且方便的方式。PHPMyAdmin是一個基于Web的數據庫管理工具,提供了許多功能,如數據庫創建、表管理、數據查詢、用戶權限設置等。本文將介紹如何通過PHPMyAdmin對MySQL數據庫進行管理,包括…

如何解決大模型返回的JSON數據前后加上```的情況

環境說明 springboot 應用使用dashscope-sdk-java對接阿里百練 deepseek v3模型 問題表現 已經指定了輸出json格式,但指令不明確,輸出JSON格式的寫法如下 注:提示詞一開始是能正常功能的,但過了幾天就出現了異常,原…

uniapp實現H5、APP、微信小程序播放.m3u8監控視頻

目錄 1.APP播放.m3u8監控視頻 2.H5播放.m3u8監控視頻 3.微信小程序播放.m3u8監控視頻 最近在寫一個uniapp實現h5、app、微信小程序兼容三端的播放監控視頻功能,我原本以為一套代碼多處運行,但事實并非如此,h5可以運行,微信小程…

螢石云實際視頻實時接入(生產環境)

螢石云視頻接入 本示例可用于實際接入螢石云開放平臺視頻,同時支持音頻輸入和輸出。 實際優化內容 1.動態獲取token 2.切換各公司和車間時,自動重新初始化播放器 let EZUIKit null; // 第三方庫引用 let EZUIKitPlayers []; // 播放器實例數組 le…

【Dify平臺】使用Dify API 實現網頁內嵌式AI助手

使用 Dify API 實現網頁內嵌式 AI 助手 一. 引言二. Dify API 概述三. 實現網頁內嵌式 AI 助手的技術架構四. 前端實現五. 后端實現六. 功能擴展與優化七. 測試與部署一. 引言 隨著 AI 技術的不斷發展,越來越多的企業希望將智能助手集成到自己的網頁中,實現用戶自動接待、問…