SpringBoot : ch11 整合RabbitMQ

前言

在当今的互联网时代,消息队列成为了构建高可靠、高性能系统的重要组件之一。RabbitMQ作为一个可靠、灵活的消息中间件,被广泛应用于各种分布式系统中。

本篇博客将介绍如何使用Spring Boot整合RabbitMQ,实现消息的发送和接收。通过这种方式,我们可以实现系统之间的解耦,提高系统的可靠性和扩展性。

在开始之前,我们需要先了解一些基本概念。RabbitMQ是一个基于AMQP(高级消息队列协议)的消息中间件,它采用了生产者-消费者模型。生产者负责发送消息到消息队列,而消费者则从队列中接收并处理消息。这种模型使得系统的各个组件可以并行工作,提高了系统的吞吐量和响应速度。

为了使用RabbitMQ,我们首先需要安装和配置它。RabbitMQ提供了丰富的功能和管理界面,可以通过简单的命令进行安装和配置。安装完成后,我们可以使用Spring Boot提供的RabbitMQ Starter来方便地集成RabbitMQ到我们的项目中。

本篇博客将从如何配置RabbitMQ开始,介绍如何创建生产者和消费者,并通过代码示例详细说明它们的使用方法。这个案例将展示如何通过消息队列传递订单信息。

一、安装RabbitMQ

教程地址:RabbitMQ 安装及配置-CSDN博客

 

二、RabbitMQ 基本概念

RabbitMQ是一个功能强大的开源消息中间件,它基于AMQP(Advanced Message Queuing Protocol,高级消息队列协议)实现了可靠的消息传递。在学习如何使用Spring Boot整合RabbitMQ之前,我们需要了解一些RabbitMQ的基本概念。

  1. 消息(Message):在RabbitMQ中,消息是指要传递的数据单元。它由一个消息体和一些可选的属性组成。消息体是实际要传递的数据,而属性则包含一些描述性的信息,例如消息的优先级、过期时间等。

  2. 生产者(Producer):生产者是消息的发送方。它负责将消息发送到RabbitMQ的交换机(exchange)中,并指定一个路由键(routing key)。交换机根据路由键将消息路由到一个或多个队列(queue)中。

  3. 交换机(Exchange):交换机是消息的分发中心,它接收从生产者发送的消息,并根据路由键将消息路由到一个或多个队列中。RabbitMQ提供了几种不同类型的交换机,包括直连交换机(direct exchange)、主题交换机(topic exchange)、扇形交换机(fanout exchange)和头交换机(headers exchange)。

  4. 队列(Queue):队列是消息的存储区域,用于存储交换机发送过来的消息。每个队列都有一个名称,并且可以绑定到一个或多个交换机上。消费者可以从队列中接收消息,并进行相应的处理。

  5. 消费者(Consumer):消费者是消息的接收方。它订阅一个或多个队列,并从队列中接收和处理消息。消费者可以以同步或异步的方式接收消息,可以手动确认消息的接收,也可以设置自动确认模式。

  6. 路由键(Routing Key):路由键是生产者在发送消息时指定的一个关键字。交换机根据路由键将消息路由到一个或多个队列中。不同类型的交换机对路由键的匹配规则有不同的要求。

以上是一些RabbitMQ的基本概念,了解这些概念对于理解和使用RabbitMQ非常重要。在后续的博客中,我们将深入探讨这些概念,并通过实际的代码示例演示它们的用法。

三、前期准备 

1、新建项目,结构如下

2、导入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</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>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>edu.nf.ch11.Ch11Application</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  1. <dependencies>部分包含了项目的依赖项。在这里,你定义了项目所需的各种依赖库。例如,spring-boot-starter-amqp是Spring Boot提供的用于集成AMQP(包括RabbitMQ)的起步依赖,而lombok是一个Java库,可以通过注解来减少样板代码。另外,还有一些用于测试的依赖项,比如spring-boot-starter-testspring-rabbit-test

  2. <dependencyManagement>部分通常用来集中管理依赖项的版本号。在这个例子中,它引入了org.springframework.boot:spring-boot-dependencies这个POM文件,并指定了版本号${spring-boot.version}。这样一来,项目中引用的Spring Boot相关的依赖都会使用统一的版本号,便于管理。

  3. <build>部分包含了项目的构建配置。其中的<plugins>定义了Maven构建过程中需要使用的插件。比如,maven-compiler-plugin指定了Java编译器的版本和编码方式,而spring-boot-maven-plugin则用于打包Spring Boot应用。在这里,它被配置为跳过执行(<skip>true</skip>),因此在实际构建过程中不会执行打包操作。

这些配置文件是构建一个基于Spring Boot和RabbitMQ的应用所必需的,它们定义了项目的依赖项、构建方式以及其他相关设置.

四、配置 RabbitMQ 配置类


@Configuration
public class RabbitConfig {

    public static final String EXCHANGE_NAME = "test.exchange";
    public static final String QUEUE_NAME = "test.queue";
    public static final String ROUTER_KEY = "KEY.TEST";

    /**
     * 装配交换机
     * @return
     */
    @Bean
    public DirectExchange exchange(){
        return new DirectExchange(EXCHANGE_NAME);
    }

    /**
     * 装配队列
     * @return
     */
    @Bean
    public Queue queue(){
        return new Queue(QUEUE_NAME,false);
    }

    /**
     * 将队列绑定到交换机
     * @return
     */
    @Bean
    public Binding binding(){
        return BindingBuilder
                .bind(queue())
                .to(exchange())
                .with(ROUTER_KEY);
    }


    /**
     * 装配自定义消息转换器
     * @return
     */
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

}

这段代码是一个用于配置RabbitMQ的类。让我解释一下其中的作用:

  1. @Configuration注解表示这是一个配置类,Spring会扫描该类并将其作为Bean定义加载到应用程序上下文中。

  2. exchange()方法使用@Bean注解将一个DirectExchange实例作为Bean加载到应用程序上下文中。DirectExchange是RabbitMQ中的一种类型的交换机,它通过指定的路由键将消息发送到与之匹配的队列。

  3. queue()方法使用@Bean注解将一个Queue实例作为Bean加载到应用程序上下文中。这个队列用于接收RabbitMQ中的消息。

  4. binding()方法使用@Bean注解将一个Binding实例作为Bean加载到应用程序上下文中。Binding用于将队列绑定到交换机并指定路由键。

  5. messageConverter()方法使用@Bean注解将一个MessageConverter实例作为Bean加载到应用程序上下文中。在这里,使用了Jackson2JsonMessageConverter,它是一个自定义的消息转换器,用于将消息以JSON格式进行序列化和反序列化。

通过使用这些Bean定义,你可以方便地配置RabbitMQ的交换机、队列、绑定关系以及消息转换器。

 

五、实体类

@Data
public class Order {

    private String orderId;

}

 存放订单信息。

 

六、生产者代码


@Slf4j
@Service
@RequiredArgsConstructor
public class ProducerService {

    private final RabbitTemplate template;

    public void sendMessage(Order order){
        // 创建消息的唯一id
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(UUID.randomUUID().toString());
        // 发送消息
        template.convertAndSend(RabbitConfig.EXCHANGE_NAME,RabbitConfig.ROUTER_KEY,order,correlationData);
        // 确认发送成功
        template.setConfirmCallback((cdata,ack,cause) -> {
            if (ack){
                log.info("消息:" + cdata.getId() + "投递成功");
            }
        });
    }

}

这段代码是一个名为ProducerService的服务类,使用了RabbitTemplate来发送消息到RabbitMQ消息队列。

在sendMessage方法中,首先创建了一个唯一的消息id,然后使用RabbitTemplate的convertAndSend方法将消息发送到指定的交换机(exchange)和路由键(routing key)。同时也传入了一个CorrelationData对象作为附加数据。

接着,通过设置RabbitTemplate的确认回调(confirm callback),可以确保消息的投递成功。在回调函数中,判断ack参数是否为true,如果为true,则表示消息投递成功,并打印相关日志信息。

 

七、消费者代码


@Slf4j
@Service
@RabbitListener(queues = RabbitConfig.QUEUE_NAME)
public class ConsumerService {


    @RabbitHandler
    public void receive(Order order){
        log.info("处理订单:" + order.getOrderId());
    }

}

 这段代码是一个消费者服务类,使用了@RabbitListener注解来监听名为RabbitConfig.QUEUE_NAME的队列。当队列中有消息到达时,会调用receive方法来处理接收到的消息。

在receive方法中,通过参数Order order来接收从队列中获取的订单消息,并打印处理订单的相关日志信息。

需要注意的是,@RabbitHandler注解用于标识该方法为消息处理方法,用来处理从队列中接收到的消息。同时,消费者需要配置好RabbitMQ的连接信息以及队列的绑定关系,确保能够正确地从指定的队列中接收消息并进行处理。

 

八、测试

1、在Rabbitmq的后台UI页面查看交换机

等下我们测试的时候,成功的话会产生一个新的交换机,我能现在查看就是为了确保等一下代码测试的结果。 

 2、测试结果

    @Autowired
    private ProducerService service;

    @Test
    void testSendMessage() {
        Order order = new Order();
        order.setOrderId("ABC123");
        service.sendMessage(order);
    }

这段代码是一个单元测试方法,用于测试ProducerService类中的sendMessage方法。首先通过@Autowired注解将ProducerService类注入到当前测试类中。

在testSendMessage方法中,创建了一个订单对象,并设置订单号为ABC123。接着调用service的sendMessage方法,将订单消息发送到RabbitMQ的消息队列中。

需要注意的是,由于这是一个单元测试方法,测试环境中需要正确配置RabbitMQ的连接信息、交换机和队列等信息,确保能够正常发送和接收消息。同时,在进行测试时,可以通过查看相关日志信息来确认消息是否成功发送和接收。

运行结果:

 

生产成功了,并且消费也成功了,我们去UI页面查看一下。 

3、查看后台的数据
 

有我们刚刚新添加的交换机。

 在消费的时候会有相应的信息显示。

这部分数据看起来是关于RabbitMQ中队列状态的概况。让我解释一下这些数据的含义:

  • Virtual host: 虚拟主机的名称。
  • Name: 队列的名称。
  • Type: 队列的类型,这里显示为 "classic",表示这是一个经典队列。
  • State: 队列的状态,这里显示为 "idle",表示队列处于空闲状态。
  • Ready: 队列中准备就绪的消息数量,这里显示为0。
  • Unacked: 未确认的消息数量,这里显示为0。
  • Total incoming: 总共进入队列的消息数量,这里显示为0.20条/秒。
  • Deliver / Get: 传递/获取消息的速率,这里显示为0.20条/秒。
  • Ack: 确认消息的速率,这里显示为0.20条/秒。

根据这些数据,队列目前处于空闲状态,但是有消息以每秒0.20条的速率进入队列,并以同样的速率被传递和确认。

注意:不会一直显示的,当消费完之后就会变回0了。

 

九、什么是RabbitMQ的生产者和消费者,区别是什么?

RabbitMQ是一种消息代理(message broker),用于在应用程序之间传递消息。在RabbitMQ中,生产者(producer)是发送消息的应用程序,而消费者(consumer)则是接收和处理这些消息的应用程序。

生产者将消息发布到一个交换机(exchange)中,交换机根据指定的路由键(routing key)将消息路由到一个或多个队列(queue)。消费者订阅这些队列,并从队列中获取消息进行处理。

在RabbitMQ中,生产者和消费者之间是解耦的,它们不需要直接知道对方的存在。生产者只需要知道如何将消息发送到正确的交换机中,而消费者只需要知道如何从正确的队列中获取消息进行处理。

使用RabbitMQ的优点是可以实现异步通信,提高系统的可伸缩性和可靠性。生产者和消费者之间的解耦也使得系统更加灵活和易于维护。

区别:

生产者(Producer)和消费者(Consumer)是在消息队列模式中的两个角色,它们有以下几个主要区别:

  1. 功能角色:生产者负责生成并发送消息到消息队列,它是消息的发送方;而消费者则从消息队列中接收并处理消息,它是消息的接收方。

  2. 数据流方向:在消息队列中,数据流是单向的。生产者将消息发布到消息队列,而消费者从消息队列中获取消息进行处理。生产者和消费者之间通过消息队列进行解耦,彼此不直接通信。

  3. 关注点不同:生产者关注的是如何生成并发送消息,通常是根据业务逻辑生成消息内容;消费者关注的是如何接收和处理消息,通常是基于业务需求对消息进行相应的处理操作。

  4. 并发性:在消息队列中,可以有多个生产者同时向一个队列发送消息,也可以有多个消费者同时从一个队列接收消息。这样可以实现消息的并发处理,提高系统的吞吐量和响应速度。

  5. 灵活性:由于生产者和消费者之间通过消息队列进行解耦,因此它们可以独立地进行扩展和部署。可以根据需要增加或删除生产者和消费者,而不会对整个系统造成影响。

总而言之,生产者负责生成和发送消息到消息队列,消费者负责接收和处理消息。它们在功能角色、数据流方向、关注点、并发性和灵活性等方面有所不同。通过合理使用生产者和消费者,可以实现高效的异步通信和解耦的系统架构。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅析函数防抖节流

防抖和节流都是前端开发中常用的优化性能的技术。 一、定义 防抖&#xff1a; 防抖指的是在事件触发后&#xff0c;在规定的时间内若再次触发&#xff0c;则重新计时&#xff0c;直到规定时间内没有再次触发事件&#xff0c;才执行事件处理。这样可以避免在短时间内频繁地触发…

SSL证书实惠品牌——JoySSL

随着互联网的普及和发展&#xff0c;网络安全问题日益严重。为了保护网站数据的安全&#xff0c;越来越多的网站开始使用SSL证书。JoySSL证书作为一款高性价比的SSL证书&#xff0c;受到了广泛的关注和好评。 目前市面上主流的证书基本上都是国外证书&#xff0c;也就是说你在验…

爬虫程序为什么一次写不好?需要一直修改BUG?

从我学习编程以来&#xff0c;尤其是在学习数据抓取采集这方面工作&#xff0c;经常遇到改不完的代码&#xff0c;我毕竟从事了8年的编程工作&#xff0c;算不上大佬&#xff0c;但是也不至于那么差。那么哪些因素导致爬虫代码一直需要修改出现BUG&#xff1f;下面来谈谈我的感…

一种新的基于物理的AlGaN/GaN HFET紧凑模型

标题&#xff1a;A new physics-based compact model for AlGaN/GaN HFETs (IEEE MTT-S International Microwave Symposium) 摘要 摘要 - 针对AlGaN/GaN HFET&#xff0c;提出了一种无拟合参数的物理解析模型。对于非饱和操作&#xff0c;建立了两个接入区和栅极下方I-V特性的…

【MVP矩阵】裁剪空间、NDC空间、屏幕空间

裁剪空间概述 裁剪空间是一个顶点乘以MVP矩阵之后所在的空间&#xff0c;Vertex Shader的输出就是在裁剪空间上&#xff08;划重点&#xff09; NDC空间概述 接上面&#xff0c;由GPU自己做透视除法将顶点转到NDC空间 两者的转换 透视除法将Clip Space顶点的4个分量都除以…

selenium 工具 的基本使用

公司每天要做工作汇报&#xff0c;汇报使用的网页版&#xff0c; 所以又想起 selenium 这个老朋友了。 再次上手&#xff0c;发现很多接口都变了&#xff0c; 怎么说呢&#xff0c; 应该是易用性更强了&#xff0c; 不过还是得重新看看&#xff0c; 我这里是python3。 pip安装…

双音多频的通信(数字信号处理实验3)

&#xff08;1&#xff09;从数字信号处理的角度分析双音多频通信&#xff0c;查阅资料了解双音多频通信的原理及工作过程&#xff0c;总结在实验报告中。 &#xff08;2&#xff09;了解DTMF接收信号时&#xff0c;离散傅立叶变化的过程。 &#xff08;3&#xff09;在程序中改…

人工智能 -- 技术概览

1、我们身处人工智能的时代 人们从早期做web开发&#xff0c;到移动端的开发&#xff1b;之后随着数据量的增大&#xff0c;人们开始研究高并发的问题&#xff1b;当数据量不断的增大&#xff0c;而人们希望数据不被浪费时&#xff0c;产生了大数据的技术&#xff0c;包括&…

真空工艺腔内潮湿有什么危害?

在半导体制程中&#xff0c;真空工艺腔被广泛使用。薄膜沉积&#xff0c;干法刻蚀&#xff0c;光刻&#xff0c;退火&#xff0c;离子注入等工序均需要在相应的真空腔室中完成相应制程。真空工艺腔在半导体制程中起着至关重要的作用&#xff0c;它能够提供一个高度控制的环境&a…

河北中洺科技-数据标注是怎样工作的?

由于人工智能系统的普及&#xff0c;各种智能场景在生活中变得普遍。然而&#xff0c;在这些极大方便我们生活的智能背后&#xff0c;数据标注似乎从未被人们所重视。数据标注是怎样的工作&#xff1f;为什么被称为人工智能训练师&#xff1f; 要想了解这些问题&#xff0c;我…

npm-工具包

npm-工具包 npm 介绍 npm&#xff08;Node Package Manager&#xff09;是用于管理和共享Node.js包&#xff08;包括代码、工具和资源&#xff09;的包管理工具 常用命令 局部安装包 npm install <package-name>: 安装指定的包 npm install <package-name> --save…

将二维数组ndarray转置ndarray.T

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将二维数组ndarray转置 ndarray.T 选择题 执行以下代码transposed_arr的输出结果为&#xff1f; import numpy as np arr np.array([[1, 2, 3], [4, 5, 6]]) transposed_arr arr.T print(&q…

json处理由fastjson换jackjson

fastjson没有jackjson稳定&#xff0c;所以换成jackjson来处理对象转json和json转对象问题。 首先下载jackjson包&#xff0c;三个都要引用 然后修改实现类 package JRT.Core.Util;import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.ja…

3种在ArcGIS Pro中制作山体阴影的方法

山体阴影可以更直观的展现地貌特点&#xff0c;表达真实的地形&#xff0c;这里为大家介绍一下在ArcGIS Pro中制作山体阴影的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的DEM数据&#xff0c;除了DEM数据&#xff0c;常见的GIS数据…

【攻防世界-misc】hit-the-core

1.将文件打开后发现文件内容为这样子的&#xff0c; 2.看文件内容里面有一串字符&#xff0c;发现除第一个大写字母不是隔四个小写以外&#xff0c;剩下的每隔四个小写字母就可以看到一个大写字母&#xff0c;刚好是ALEXCTF&#xff0c;按这个规律找下去&#xff0c;应该就可以…

Kubernetes入门篇

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容Kubernetes是什么&#xff1f;为什么需要 Kubernetes&#xff0c;它能做什么&#xff1f;Kubernetes 版本进化Kubernetes 概念Kubernetes 中 3 个重要概念 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介…

在线陪诊系统: 医疗科技的崭新前沿

在医学科技的快速发展中&#xff0c;在线陪诊系统正成为医疗服务领域的创新力量。通过结合互联网和先进的远程技术&#xff0c;这一系统为患者和医生提供了更为便捷、高效的医疗体验。本文将深入探讨在线陪诊系统的技术背后的核心代码和实现原理。 技术背后的关键代码 在线陪…

精力管理金字塔

精力管理金字塔 由协和医学院的张遇升博士在《掌控精力&#xff1a;不疲惫的身心管理术》一书中提出&#xff0c;分层次对精力管理提出了解析和有效的建议。 模型介绍 精力管理是一个可以学会的技能&#xff0c;学会了科学的精力管理方法&#xff0c;就能使自己的精力越来越好…

webpack项目工程初始化

一、初始化项目 默认系统已经安装node //初始化 pnpm init//安装webpack pnpm i -D webpack webpack-cli 新建一个index.html的入口文件 新建一个src文件存放js代码&#xff0c;src里面新建一个index.js package.josn配置打包命令 {"name": "webpack-cs&q…

【算法】算法题-20231129

这里写目录标题 一、15. 三数之和二、205. 同构字符串三、383. 赎金信 一、15. 三数之和 提示 中等 6.5K 相关企业 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] …