RabbitMQ第三个实操小案例——发布者/订阅者(Publish/Subscribe)、广播交换器(FanoutExchange)

2023-11-12

RabbitMQ第三个实操小案例——发布者/订阅者(Publish/Subscribe)、广播交换器(FanoutExchange)

发布者/订阅者 模型如下:
在这里插入图片描述

他与前面两个小案例最大的区别就是,他的消息不是阅完即焚的。他允许将同一条消息发送给多个消费者。而实现此操作的原因是加入了我们的交换机(exchange)。

在发布者和订阅者的模型中,各个组件的功能如下

  • Publisher:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
  • Exchange:交换机,一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有以下3种类型:
    • Fanout:广播,将消息交给所有绑定到交换机的队列
    • Direct:定向,把消息交给符合指定routing key 的队列
    • Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
  • Queue:消息队列也与以前一样,接收消息、缓存消息。
  • Consumer:消费者,与以前一样,订阅队列,没有变化

注意:交换机他只负责消息的转发,并不存储消息,如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!!

OK,这么解释肯定是不够的,下面我们就来说一下第一种交换机类型——Fanout(广播)在Java中的具体使用方式

写法一、配置类配置方式

步骤一、在消费者服务中,利用代码声明队列、交换机,并将两者进行绑定。
SpringAMQP提供的**交换机(Exchange)、队列(Queue)、绑定(Binding)**的API如下:
在这里插入图片描述
要将我们的队列绑定到交换机,我们需要编写我们的配置类如下:

package com.demo.mq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {
    /**
     *  声明FanoutExchange(广播交换机)
     */
    @Bean
    public FanoutExchange fanoutExchange(){
        //交换机的名称
        return new FanoutExchange("exchange.fanout");
    }

    /**
     *  声明第一个队列
     */
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }

    /**
     *  声明第二个队列
     */
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }

    /**
     *  绑定 队列1 到 交换机
     */
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    /**
     *  绑定 队列2 到 交换机
     */
    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

写完配置类,我们重启一下我们的消费者服务类,然后我们到RabbitMQ上看一下我们的交换机和队列。

可以看到,确实多了一个交换机叫 exchange.fanout。
在这里插入图片描述

我们再看一下队列,可以看到,我们两个队列也都注册成功了。
在这里插入图片描述
点击我们刚才新增的交换机,打开它的Bindings,可以看到这个交换机他告诉我们,他的消息是会转发到 fanout.queue1 和 fanout.queue2中:
在这里插入图片描述

ok,我们接着往下写:

**步骤二、在消费者服务中,编写两个消费者方法,分别监听 fanout.queue1 和 fanout.queue2。 **.

监听的方法,现在应该已经写得滚瓜烂熟了吧,这里就直接贴代码了。
1、编写的类记得加 @Component 将这个监听的类注册到 Spring容器中。
2、监听哪个queue,那么就写对应的方法,并在方法上方添加@RabbitListener注解,用queues属性标明要监听的queue即可。(如果有多个,那么用 @RabbitListener(queues = {“queueName1”, “queueName2”})表示即可。

@Component
public class SpringRabbitListener {
    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg){
        System.out.println("监听到 fanout.queue1 的消息为:【"+ msg +"】");
    }

    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg){
        System.out.println("监听到 fanout.queue2 的消息为:【"+ msg +"】");
    }
}

步骤三、在发布者服务中,编写测试方法,向交换机 exchange.fanout 发送消息。

    @Test
    public void testFanoutExchange(){
        //交换机名称
        String exchangeName = "exchange.fanout";
        //消息
        String msg = "Hello,av8d!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName, "", msg);
    }

这里的rabbitTemplate.convertAndSend接受三个参数,分别是

public void convertAndSend(String exchange,
                           String routingKey,
                           Object object)
  1. exchange:交换机的名称
  2. routeKey:routeKey值(还不需要用到,先不管他,给个"")
  3. object:发送的消息

写完测试方法,我们跑一下我们的测试方法,然后看一下我们消费者的控制台如下:
在这里插入图片描述
可以看到,只发布了一条消息,但是通过交换机发布给两个Queue后,我们消费者的两个方法都监听到了我们同一条消息。

写法二、注解方式(@RabbitListener)

如果以前尝试了上面的写法,记得把配置类的 @Configuration 注释掉

//@Configuration
public class FanoutConfig {
...
}

然后把刚才写的两个方法注释掉。

/**
    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg){
        System.out.println("监听到 fanout.queue1 的消息为:【"+ msg +"】");
    }

    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg){
        System.out.println("监听到 fanout.queue2 的消息为:【"+ msg +"】");
    }
**/

接下来,我们就开始写我们使用注解声明队列的方法。

步骤一、配置我们的RabbitMQ。(只要使用RabbitMQ,都必须要配置)

spring:
  rabbitmq:
    host: 192.168.83.134
    port: 5672
    virtual-host: /
    username: admin
    password: root
    listener:
      simple:
        prefetch: 1

步骤二、直接写我们的监听方法。(使用@RabbitListener注解写我们的路由方式、路由名称以及我们的队列名即可)

@Component
public class SpringRabbitListener {
	@RabbitListener(bindings = @QueueBinding(
	        value = @Queue(name = "fanout.queue1"),
	        exchange = @Exchange(name = "exchange.fanout", type = ExchangeTypes.FANOUT)
	))
	public void listenFanoutQueue1(String msg){
	    System.out.println("监听到 fanout.queue1 的消息为:【" + msg+"】");
	}
	
	@RabbitListener(bindings = @QueueBinding(
	        value = @Queue(name = "fanout.queue2"),
	        exchange = @Exchange(name = "exchange.fanout", type = ExchangeTypes.FANOUT)
	))
	public void listenFanoutQueue2(String msg){
	    System.out.println("监听到 fanout.queue2 的消息为:【" + msg+"】");
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RabbitMQ第三个实操小案例——发布者/订阅者(Publish/Subscribe)、广播交换器(FanoutExchange) 的相关文章

  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s

随机推荐

  • sEnginScriptError Component is not found in path "components/..."

    小程序开发报错 sEnginScriptError Component is not found in path components cesh using by pages playlist playlist onAppRoute Err
  • 更换JDK版本不生效的问题解决方案

    1 首先检查环境变量是否修改完成 环境变量配置 PATH JAVA HOME bin JAVA HOME C Program Files Java jdk1 8 1 131 选择自己电脑上JDK的安装路径 2 输入 javac 检查JDK是
  • 力扣1342. 将数字变成 0 的操作次数(java+python)

    给你一个非负整数 num 请你返回将它变成 0 所需要的步数 如果当前数字是偶数 你需要把它除以 2 否则 减去 1 示例 1 输入 num 14 输出 6 解释 步骤 1 14 是偶数 除以 2 得到 7 步骤 2 7 是奇数 减 1 得
  • java Field.canAccess 和 Field.isAccessible

    如果 Field isAccessible 已经过时 则使用 Field canAccess 官方Api boolean Field canAccess Object obj Object obj an instance object of
  • Invalid character found in the request target.The valid characters are defined in RFC 7230 and RFC39

    背景 在将tomcat升级到7 0 81版后 发现系统的有些功能不能使用了 查询日志发现是有些地址直接被tomcat认为存在不合法字符 返回HTTP 400错误响应 错入信息如下 原因分析 经了解 这个问题是高版本tomcat中的新特性 就
  • Intellij IDEA 2019无法联网,无法下载插件问题解决办法

    Intellij IDEA 2019无法联网 无法下载插件问题解决办法 非法不多说直接上图 第一步 第二步 2019 2 之后没有这一步 第三步 记得重启哦 lt 完 gt
  • 代理服务器列表(20100116)

    经测试 今天发布的代理服务器全部都是免费可用的 211 152 11 30 80 69 119 28 234 8085 72 196 11 73 8085 222 66 116 110 8080 41 223 143 16 8080 122
  • 5.1劳动节,Happy May Day!(为什么要调休啊?)

    国际劳动节又称 五一国际劳动节 国际示威游行日 英语 International Workers Day May Day 是世界上80多个国家的全国性节日 定在每年的五月一日 它是全世界劳动人民共同拥有的节日 1889年7月 由恩格斯领导的
  • Unity中的宏定义

    有时候我们需要使用区分不同平台来实现不同的逻辑 这个时候就用到宏定义了 基本语法 if UNITY EDITOR WIN UNITY STANDALONE elif UNITY ANDROID else endif 宏定义可以直接写在类中
  • 基于STM32的正点原子LORA模块通信网络

    LoRa是semtech公司开发的一种低功耗局域网无线标准 其名称 LoRa 是远距离无线电 Long Range Radio 它最大特点就是在同样的功耗条件下比其他无线方式传播的距离更远 实现了低功耗和远距离的统一 它在同样的功耗下比传统
  • 解决“yarn : 无法加载文件 C:\Users\quber\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本”问题

    我们在使用yarn命令的时候 可能会出现如下图所示的错误 出现此错误的原因是本地计算机上运行你编写的未签名脚本和来自其他用户的签名脚本 可以使用如下命令将计算机上的执行策略更改为RemoteSigned 执行命令set ExecutionP
  • 6-3 逆序数据建立链表(20 分)_头插法建链表

    6 3 逆序数据建立链表 20 分 本题要求实现一个函数 按输入数据的逆序建立一个链表 函数接口定义 struct ListNode createlist 函数createlist利用scanf从输入中获取一系列正整数 当读到 1时表示输入
  • CMake常用命令(二) project命令

    文章目录 语法 作用 参数 举例 示例1 基础用法 示例2 VERSION用法 示例3 DESCRIPTION用法 示例4 HOMEPAGE URL用法 示例4 LANGUAGES用法 更多细节 参考 语法 project
  • 【Python库系列】超详细的NumPy入门

    目录 一 数组的创建 1 1 创建数组 1 2 数组的性质 二 数组的存载 2 1 numpy 自身的 npy 格式 2 2 文本 txt 格式 2 3 文本 csv 格式 三 数组的获取 3 1 正规索引 3 2 布尔索引 3 3 花式索
  • 多类隶属度的模糊支持向量机(FSVM)

    模糊支持向量机 FSVM 多类隶属度分析 1 传统FSVM 隶属度分析 2 改进的FSVM 隶属度分析 3 FSVM多类隶属度分析 4 评估分类效果 不定期遴选一些高质量期刊论文 进行介绍 内容不详加解释 重在学习文章的思路 模糊隶属度来描
  • EMC基础知识

    一 概述 传导实验为测试被测设备对外界的骚扰的强度的实验 测试的频谱为150K 30MHz 充分理解实验数据 对设计整改会起到关键性作用 以下对实验波形及数据 设计整改方向进行简要说明 二 测试频域图解读 以上2张波形 是测试中经常看到的2
  • 如何用vue实现文本的编辑

    文章数据是通过后台返回html数据 之后前端通过遍历生成一个大的html 然后渲染到页面上 我如果我想要给这个文章新添加一个编辑功能应该怎么实现 文章内容不便展示 只通过文字描述完成本功能 一般的话 编辑文本可以才用富文本编辑器或者采用wo
  • java 基础重学(二)-基础知识

    1 基本数据类型 2 自动拆装箱 3 String 4 关键字 5 集合类 6 枚举 7 IO 8 反射 9 动态代理 10 序列化 11 注解 12 JMS 13 JMX 14 泛型 15 单元测试 16 正则表达式 17 异常 18 时
  • 2021年最推荐的十大进销存管理软件排名

    2021年过去一半了 相信不少商家都要准备开始在忙着盘点自己库存 对账 整理数据报表 有的人选对了店铺管理软件 只需动动手指就能快速搞定自己需要的数据 然而有的人每天晚上加班加点计算盘点 到头来数据还是一团糟 只因为没有选对店铺管理软件或者
  • RabbitMQ第三个实操小案例——发布者/订阅者(Publish/Subscribe)、广播交换器(FanoutExchange)

    文章目录 RabbitMQ第三个实操小案例 发布者 订阅者 Publish Subscribe 广播交换器 FanoutExchange 写法一 配置类配置方式 写法二 注解方式 RabbitListener RabbitMQ第三个实操小案