【RabbitMQ】Spring Boot 结合 RabbitMQ 完成应用间的通信

news2025/3/14 1:09:16

   🔥个人主页: 中草药

🔥专栏:【中间件】企业级中间件剖析


 Spring 框架与 RabbitMQ 的整合主要通过 Spring AMQP(Advanced Message Queuing Protocol)模块实现,提供了便捷的消息队列开发能力。

引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

配置

#配置RabbitMQ的基本信息
spring:
 rabbitmq:
 host: 110.41.51.65
 port: 15673 #默认为5672
 username: study
 password: study
 virtual-host: bite #默认值为

#或者以下这种方式
 rabbitmq:
   addresses: #amqp://username:password@Ip:port/virtual-host

一、工作队列模式(Work Queue)

场景:多个消费者共享一个队列,消息被轮询分发(Round-Robin),用于任务分发和负载均衡(如耗时任务处理)。

producer

@RestController
@RequestMapping("/producer")
public class ProducerController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RequestMapping("/work")
    public String work(){
        //使用内置交换机 RoutingKey 和队列名称一致
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("", Constants.WORK_QUEUE,"Hello World"+i);
        }
        return "OK";
    }
}

@RabbitListener 是 Spring 框架中用于监听 RabbitMQ 队列的注解,通过使用这个注解,可以定义一个方法,以便从 RabbitMQ 队列中接收消息(相当于消费者)。该注解支持多种参数类型,这些参数类型代表了从 RabbitMQ 接收到的消息和相关信息。

以下是一些常用的参数类型:

  1. String:返回消息的内容。
  2. Messageorg.springframework.amqp.core.Message):Spring AMQP 的 Message 类,返回原始的消息体以及消息的属性,如消息 ID、内容、队列信息等。
  3. Channelcom.rabbitmq.client.Channel):RabbitMQ 的通道对象,可以用于进行更高级的操作,如手动确认消息 。
@Component
public class WorkListener {

    @RabbitListener(queues = Constants.WORK_QUEUE)
    public void queueListener1(Message message, Channel channel) {
        System.out.println("Listener1:["+Constants.WORK_QUEUE+"]"+message+",channel:"+channel);
    }

    @RabbitListener(queues = Constants.WORK_QUEUE)
    public void queueListener2(String message) {
        System.out.println("Listener2:["+Constants.WORK_QUEUE+"]"+message);
    }
}

观察控制台

轮询分发:默认按顺序将消息分发给不同消费者。

二、发布订阅模式(Publish/Subscribe)

场景:消息广播到所有绑定的队列(如日志广播、事件通知),使用 Fanout 交换机

声明使用交换机和队列 并绑定

@Configuration
public class RabbitMQConfig {
    @Bean("fanoutQueue1")
    public Queue funoutQueue1() {
        return QueueBuilder.durable(Constants.FUNOUT_QUEUE1).build();
    }

    @Bean("fanoutQueue2")
    public Queue funoutQueue2() {
        return QueueBuilder.durable(Constants.FUNOUT_QUEUE2).build();
    }

    @Bean("funoutExchange")
    public FanoutExchange funoutExchange(){
        return ExchangeBuilder.fanoutExchange(Constants.FUNOUT_EXCHANGE).durable(true).build();
    }

    @Bean("funoutQueueBinding1")
    public Binding funoutQueueBinding1(@Qualifier("fanoutQueue1") Queue queue,@Qualifier("funoutExchange") FanoutExchange funoutExchange){
        return BindingBuilder.bind(queue).to(funoutExchange);
    }

    @Bean("funoutQueueBinding2")
    public Binding funoutQueueBinding2(@Qualifier("fanoutQueue2") Queue queue,@Qualifier("funoutExchange") FanoutExchange funoutExchange){
        return BindingBuilder.bind(queue).to(funoutExchange);
    }
}

producer


@RestController
@RequestMapping("/producer")
public class ProducerController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RequestMapping("/funout")
    public String funout(){
        rabbitTemplate.convertAndSend(Constants.FUNOUT_EXCHANGE,"","Hello Spring funout");
        return "OK";
    }
}

listener

@Component
public class FunoutListener {

    @RabbitListener(queues = Constants.FUNOUT_QUEUE1)
    public void queueListener1(String message) {
        System.out.println("Listener1:["+Constants.FUNOUT_QUEUE1+"]"+message);
    }

    @RabbitListener(queues = Constants.FUNOUT_QUEUE2)
    public void queueListener2(String message) {
        System.out.println("Listener2:["+Constants.FUNOUT_QUEUE2+"]"+message);
    }
}

在实际开发之中,一个 listener 监听一个 queue 

三、路由模式(Routing)

场景:根据 路由键(Routing Key) 精准匹配,将消息发送到指定队列,使用 Direct 交换机

声明使用交换机和队列 并绑定

@Configuration
public class RabbitMQConfig {
     //direct
    @Bean("directQueue1")
    public Queue directQueue1() {
        return QueueBuilder.durable(Constants.DIRECT_QUEUE1).build();
    }

    @Bean("directQueue2")
    public Queue directQueue2() {
        return QueueBuilder.durable(Constants.DIRECT_QUEUE2).build();
    }

    @Bean("directExchange")
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange(Constants.DIRECT_EXCHANGE).durable(true).build();
    }

    @Bean("directQueueBinding1")
    public Binding directQueueBinding1(@Qualifier("directQueue1") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){
        return BindingBuilder.bind(queue).to(directExchange).with("orange");
    }

    @Bean("directQueueBinding2")
    public Binding directQueueBinding2(@Qualifier("directQueue2") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){
        return BindingBuilder.bind(queue).to(directExchange).with("black");
    }

    @Bean("directQueueBinding3")
    public Binding directQueueBinding3(@Qualifier("directQueue2") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){
        return BindingBuilder.bind(queue).to(directExchange).with("orange");
    }
}

producer


@RestController
@RequestMapping("/producer")
public class ProducerController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

      @RequestMapping("/direct/{routingKey}")
    public String direct(@PathVariable String routingKey){
        rabbitTemplate.convertAndSend(Constants.DIRECT_EXCHANGE,routingKey,"Hello Spring direct "+routingKey);
        return "direct OK";
    }
}

listener

@Component
public class DirectListener {

    @RabbitListener(queues = Constants.DIRECT_QUEUE1)
    public void queueListener1(String message) {
        System.out.println("Listener1:["+Constants.DIRECT_QUEUE1+"]"+message);
    }

    @RabbitListener(queues = Constants.DIRECT_QUEUE2)
    public void queueListener2(String message) {
        System.out.println("Listener2:["+Constants.DIRECT_QUEUE2+"]"+message);
    }
}

如果某一个队列即绑定了black和orange,将会分别发送到队列

四、通配符模式(Topics)

场景:根据路由键的 通配符规则 匹配队列,使用 Topic 交换机,支持 *(匹配一个单词)和 #(匹配多个单词)。

Topics 和 Routing 模式的区别是:

  1. topics 模式使用的交换机类型为 topic (Routing 模式使用的交换机类型为 direct)
  2. topic 类型的交换机在匹配规则上进行了扩展,Binding Key 支持通配符匹配

声明使用交换机和队列 并绑定

@Configuration
public class RabbitMQConfig {
      //TOPIC
    @Bean("topicExchange")
    public TopicExchange topicExchange(){
        return ExchangeBuilder.topicExchange(Constants.TOPIC_EXCHANGE).durable(true).build();
    }

    @Bean("topicQueue1")
    public Queue topicQueue1(){
        return QueueBuilder.durable(Constants.TOPIC_QUEUE1).build();
    }

    @Bean("topicQueue2")
    public Queue topicQueue2(){
        return QueueBuilder.durable(Constants.TOPIC_QUEUE2).build();
    }

    @Bean("topicQueueBinding1")
    public Binding topicQueueBinding1(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue1") Queue topicQueue){
        return BindingBuilder.bind(topicQueue).to(topicExchange()).with("*.orange.*");
    }

    @Bean("topicQueueBinding2")
    public Binding topicQueueBinding2(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue2") Queue topicQueue){
        return BindingBuilder.bind(topicQueue).to(topicExchange).with("*.*.rabbit");
    }

    @Bean("topicQueueBinding3")
    public Binding topicQueueBinding3(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue2") Queue topicQueue){
        return BindingBuilder.bind(topicQueue).to(topicExchange).with("lazy.#");
    }
}

producer


@RestController
@RequestMapping("/producer")
public class ProducerController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

      @RequestMapping("/topic/{routingKey}")
    public String topic(@PathVariable String routingKey){
        rabbitTemplate.convertAndSend(Constants.TOPIC_EXCHANGE,routingKey,"Hello Spring topic "+routingKey);
        return "topic OK";
    }
}

listener

@Component
public class TopicListener {

    @RabbitListener(queues = Constants.TOPIC_QUEUE1)
    public void queueListener1(String message) {
        System.out.println("Listener1:["+Constants.TOPIC_QUEUE1+"]"+message);
    }

    @RabbitListener(queues = Constants.TOPIC_QUEUE2)
    public void queueListener2(String message) {
        System.out.println("Listener2:["+Constants.TOPIC_QUEUE2+"]"+message);
    }
}

五、完成应用通信

SpringBoot 整合 RabbitMQ 实现应用通信是微服务/分布式系统中常见的异步解耦方案。

以此图为实例

订单系统

@Configuration
public class RabbitMQConfig {
    @Bean("orderQueue")
    public Queue orderQueue() {
        return QueueBuilder.durable("order.create").build();
    }
}


@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RequestMapping("/create")
    public String create(){
        rabbitTemplate.convertAndSend("","order.create","订单信息,订单ID:"+ UUID.randomUUID());
        //这里仅仅是模拟演示,实际的下单操作比较复杂,包括参数的校验,数据库存储等等 业务代码省略
        return "下单成功";
    }
}

 物流系统

@Component
@RabbitListener(queues = "order.create")
public class OrderListener {
    @RabbitHandler
    //该注解根据所识别的数据类型不同自动分配不同的方法
    public void handleOrder(String orderInfo) {
        System.out.println("接收到新的订单消息:"+orderInfo);
        //接收到订单消息后,进行相应的业务出路 代码省略
    }

    @RabbitHandler
    //在此处为方便演示我们将order-service 让此项目应用
    //正确的做法是将OrderInfo抽取出来单独作为一个包,两个service都引用这个包
    public void handleOrder2(OrderInfo orderInfo) {
        System.out.println("接收到新的订单消息:"+orderInfo);
    }
}

@RabbitHandler 注解用于标记方法,这些方法会根据消息的类型来处理接收到的消息。当一个消息监听器容器接收到消息时,它会根据消息的类型选择合适的 @RabbitHandler 注解的方法来处理该消息。 

测试结果

当在发送的是一个对象时,为保证对象的可读性,我们要保证对象可被序列化,且通过 Jackson2JsonMessageConverter 将其从原生序列化改为Json格式

@Configuration
public class RabbitMQConfig {
    @Bean
    public Jackson2JsonMessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(messageConverter());
        return rabbitTemplate;
    }
}

对于Listener,为保证同样具有解读json的能力,也应该去加上相同的配置 

@Data
public class OrderInfo implements Serializable {//实现序列化接口
    private String orderId;
    private String name;
}

 可观察结果


对时间的慷慨,就等于慢性自杀。——奥斯特洛夫斯基

🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀

以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐

  制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2314572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch系列教程:可视化Pytorch模型训练过程

深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解&#xff0c;使我们能够做出合理的决策。训练进度必须可视化的两种方法是&#xff1a;使用Matplotlib和Tensor Board。在本文…

electron+vue+webview内嵌网页并注入js

vue内嵌网页可以使用iframe实现内嵌网页&#xff0c;但是只能通过postMessage间接通信&#xff0c;在electron环境下&#xff0c;vue可以直接使用webview来内嵌网页&#xff0c;支持 executeJavaScript、postMessage、send 等丰富的通信机制。 使用 webview的优势 性能更佳&…

利用OpenResty拦截SQL注入

需求 客户的一个老项目被相关部门检测不安全&#xff0c;报告为sql注入。不想改代码&#xff0c;改项目&#xff0c;所以想到利用nginx去做一些数据校验拦截。也就是前端传一些用于sql注入的非法字符或者数据库的关键字这些&#xff0c;都给拦截掉&#xff0c;从而实现拦截sql…

CAD文件转换为STL

AutoCAD与STL格式简介 AutoCAD软件是由美国欧特克有限公司&#xff08;Autodesk&#xff09;出品的一款自动计算机辅助设计软件&#xff0c;可以用于绘制二维制图和基本三维设计&#xff0c;通过它无需懂得编程&#xff0c;即可自动制图&#xff0c;因此它在全球广泛使用&…

QT:串口上位机

创建工程 布局UI界面 设置名称 设置数据 设置波特率 波特率默认9600 设置数据位 数据位默认8 设置停止位 设置校验位 调整串口设置、接收设置、发送设置为Group Box 修改配置 QT core gui serialport 代码详解 mianwindow.h 首先在mianwindow.h当中定义一个串口指…

win32汇编环境,网络编程入门之二

;运行效果 ;win32汇编环境,网络编程入门之二 ;本教程在前一教程的基础上&#xff0c;研究一下如何得到服务器的返回的信息 ;正常的逻辑是连接上了&#xff0c;然后我发送什么&#xff0c;它返回什么&#xff0c;但是这有一个很尴尬的问题。 ;就是如何表现出来。因为网络可能有延…

【认识OpenThread协议】

OpenThread 是一种基于 IPv6 、IEEE 802.15.4 标准的低功耗无线 Mesh 网络协议&#xff0c;主要用于智能家居、物联网设备等场景。它的设计目标是实现设备之间的高效通信、低功耗运行和高可靠性。 OpenThread官方文档 ① 特性 低功耗: 适合电池供电的设备。 Mesh 网络: 支持多…

字节跳动 —— 建筑物组合(滑动窗口+溢出问题)

原题描述&#xff1a; 题目精炼&#xff1a; 给定N个建筑物的位置和一个距离D&#xff0c;选取3个建筑物作为埋伏点&#xff0c;找出所有可能的建筑物组合&#xff0c;使得每组中的建筑物之间的最大距离不超过D。最后&#xff0c;输出不同埋伏方案的数量并对99997867取模。 识…

开源数字人模型Heygem

一、Heygem是什么 Heygem 是硅基智能推出的开源数字人模型&#xff0c;专为 Windows 系统设计。基于先进的AI技术&#xff0c;仅需1秒视频或1张照片&#xff0c;能在30秒内完成数字人形象和声音克隆&#xff0c;在60秒内合成4K超高清视频。Heygem支持多语言输出、多表情动作&a…

Linux远程工具SecureCRT下载安装和使用

SecureCRT下载安装和使用 SecureCRT是一款功能强大的终端仿真软件&#xff0c;它支持SSH、Telnet等多种协议&#xff0c;可以连接和管理基于Unix和Windows的远程主机和网络设备。SecureCRT提供了语法高亮、多标签页管理、会话管理、脚本编辑等便捷功能&#xff0c;安全性高、操…

江科大51单片机笔记【15】直流电机驱动(PWM)

写在前言 此为博主自学江科大51单片机&#xff08;B站&#xff09;的笔记&#xff0c;方便后续重温知识 在后面的章节中&#xff0c;为了防止篇幅过长和易于查找&#xff0c;我把一个小节分成两部分来发&#xff0c;上章节主要是关于本节课的硬件介绍、电路图、原理图等理论…

【网络协议详解】——QOS技术(学习笔记)

目录 QoS简介 QoS产生的背景 QoS服务模型 基于DiffServ模型的QoS组成 MQC简介 MQC三要素 MQC配置流程 优先级映射配置(DiffServ域模式) 优先级映射概述 优先级映射原理描述 优先级映射 PHB行为 流量监管、流量整形和接口限速简介 流量监管 流量整形 接口限速…

Spring学习笔记:工厂模式与反射机制实现解耦

1.什么是Spring? spring是一个开源轻量级的java开发应用框架&#xff0c;可以简化企业级应用开发 轻量级 1.轻量级(对于运行环境没有额外要求) 2.代码移植性高(不需要实现额外接口) JavaEE的解决方案 Spring更像是一种解决方案&#xff0c;对于控制层&#xff0c;它有Spring…

pytest数据库测试文章推荐

参考链接&#xff1a; 第一部分&#xff1a;http://alextechrants.blogspot.fi/2013/08/unit-testing-sqlalchemy-apps.html第二部分&#xff1a;http://alextechrants.blogspot.fi/2014/01/unit-testing-sqlalchemy-apps-part-2.html

vue3 二次封装uni-ui中的组件,并且组件中有 v-model 的解决方法

在使用uniappvue3开发中&#xff0c; 使用了uni-ui的组件&#xff0c;但是我们也需要自定义组件&#xff0c;比如我要自定一个picker 的组件&#xff0c; 是在 uni-data-picker 组件的基础上进行封装的 父组件中的代码 <classesselect :selectclass"selectclass"…

探索高性能AI识别和边缘计算 | NVIDIA Jetson Orin Nano 8GB 开发套件的全面测评

随着边缘计算和人工智能技术的迅速发展&#xff0c;性能强大的嵌入式AI开发板成为开发者和企业关注的焦点。NVIDIA近期推出的Jetson Orin Nano 8GB开发套件&#xff0c;凭借其40 TOPS算力、高效的Ampere架构GPU以及出色的边缘AI能力&#xff0c;引起了广泛关注。本文将从配置性…

【学习笔记】《逆向工程核心原理》03.abex‘crackme-2、函数的调用约定、视频讲座-Tut.ReverseMe1

文章目录 abexcrackme-21. Visual Basic文件的特征1.1. VB专用引擎1.2. 本地代码与伪代码1.3. 事件处理程序1.4. 未文档化的结构体 2. 开始调试2.1. 间接调用2.2. RT_MainStruct结构体2.3. ThunRTMain()函数 3. 分析crackme3.1. 检索字符串3.2. 查找字符串地址3.3. 生成Serial的…

React基础之项目实战

规范的项目结构 安装scss npm install sass -D 安装Ant Design组件库 内置了一些常用的组件 npm install antd --save 路由基础配置 npm i react-router-dom 路由基本入口 import Layout from "../page/Layout"; import Login from "../page/Login"; impor…

SAP-ABAP:SAP数据库视图的创建图文详解

在SAP ABAP中&#xff0c;数据库视图&#xff08;Database View&#xff09;是通过ABAP字典&#xff08;ABAP Dictionary&#xff09;创建的。数据库视图是基于一个或多个数据库表的虚拟表&#xff0c;它允许你定义一种逻辑视图来访问数据。以下是创建数据库视图的步骤&#xf…

基于深度学习的肺炎X光影像自动诊断系统实现,真实操作案例分享,值得学习!

医疗影像智能化的技术演进 医学影像分析正经历从人工判读到AI辅助诊断的革命性转变。传统放射科医师分析胸部X光片需要8-12年专业训练&#xff0c;而基于深度学习的智能系统可在秒级完成检测。本文将以肺炎X光检测为切入点&#xff0c;详解从数据预处理到模型部署的全流程实现。…