【RabbitMQ——SpringBoot整合】

1. fanout模式

Fanout 交换器(Exchange)是 RabbitMQ 中的一种消息路由模式。它是一种广播式的交换器,会将接收到的消息发送给所有绑定到该交换器的队列,而不考虑路由键(routing key)。这意味着无论消息发布时指定了什么路由键,Fanout 交换器都会忽略这些信息,并简单地将消息复制并分发给所有的绑定队列。

1.1 配置类

@Configuration
public class FanoutRabbitConfig {

    // 1. 声明注册fanout模式的交换机
    @Bean
    public FanoutExchange fanoutOrderExchange() {
        //  return new DirectExchange("TestDirectExchange",true,true);
        return new FanoutExchange("fanout_order_exchange", true, false);
    }
    // 2. 申明队列sms.fanout.queue  email.fanout.queue duanxin.fanout.queue
    @Bean
    public Queue fanoutEmailQueue() {
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        //   return new Queue("TestDirectQueue",true,true,false);
        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("email.fanout.queue", true);
    }
    @Bean
    public Queue fanoutSmsQueue() {
        return new Queue("sms.fanout.queue", true);
    }
    @Bean
    public Queue fanoutWeixinQueue() {
        return new Queue("weixin.fanout.queue", true);
    }
    // 3. 完成绑定关系
    @Bean
    public Binding fanoutBindingDirect1() {
        return BindingBuilder.bind(fanoutEmailQueue()).to(fanoutOrderExchange());
    }
    @Bean
    public Binding fanoutBindingDirect2() {
        return BindingBuilder.bind(fanoutSmsQueue()).to(fanoutOrderExchange());
    }
    @Bean
    public Binding fanoutBindingDirect3() {
        return BindingBuilder.bind(fanoutWeixinQueue()).to(fanoutOrderExchange());
    }

}

1.2 生产者

public void makeOrder(Long userId, Long productId, int num) {
    // 1: 模拟用户下单
    String orderNumer = UUID.randomUUID().toString();
    // 2: 根据商品id productId 去查询商品的库存
    // int numstore = productSerivce.getProductNum(productId);
    // 3:判断库存是否充足
    // if(num >  numstore ){ return  "商品库存不足..."; }
    // 4: 下单逻辑
    // orderService.saveOrder(order);
    // 5: 下单成功要扣减库存
    // 6: 下单完成以后
    System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
    // 发送订单信息给RabbitMQ fanout
    String exchangeName = "fanout_order_exchange";
    String routeKey = "";
    rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
}

1.3 消费者

// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"email.fanout.queue"})
@Component
public class FanoutEmailService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("fanout-email-------------->" + message);
    }
}
// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"sms.fanout.queue"})
@Component
public class FanoutSMSService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("fanout-sms-------------->" + message);
    }
}
@RabbitListener(queues = {"weixin.fanout.queue"})
@Component
public class FanoutWeixinService {

    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("fanout-weixin-------------->" + message);
    }
}

2. direct模式

Direct 交换器根据消息的路由键(routing key)和队列绑定时指定的路由键进行精确匹配来决定消息的分发。如果一个队列绑定了带有特定路由键的 Direct 交换器,那么只有当发布到该交换器的消息携带相同的路由键时,消息才会被发送到这个队列。

2.1 配置类

注意配置类中声明的交换机的类型,以及队列携带的路由key

@Configuration
public class DirectRabbitConfig {

    // 1. 声明注册fanout模式的交换机
    @Bean
    public DirectExchange directOrderExchange() {
        return new DirectExchange("direct_order_exchange", true, false);
    }
    // 2. 申明队列sms.fanout.queue  email.fanout.queue duanxin.fanout.queue
    @Bean
    public Queue directEmailQueue() {
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        //   return new Queue("TestDirectQueue",true,true,false);
        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("email.direct.queue", true);
    }
    @Bean
    public Queue directSmsQueue() {
        return new Queue("sms.direct.queue", true);
    }
    @Bean
    public Queue directWeixinQueue() {
        return new Queue("weixin.direct.queue", true);
    }
    // 3. 完成绑定关系
    @Bean
    public Binding directBindingDirect1() {
        return BindingBuilder.bind(directWeixinQueue()).to(directOrderExchange()).with("weixin");
    }
    @Bean
    public Binding directBindingDirect2() {
        return BindingBuilder.bind(directSmsQueue()).to(directOrderExchange()).with("sms");
    }
    @Bean
    public Binding directBindingDirect3() {
        return BindingBuilder.bind(directEmailQueue()).to(directOrderExchange()).with("email");
    }

}

2.2 生产者

    public void makeOrderDirect(Long userId, Long productId, int num) {
        // 1: 模拟用户下单
        String orderNumer = UUID.randomUUID().toString();
        // 2: 根据商品id productId 去查询商品的库存
        // int numstore = productSerivce.getProductNum(productId);
        // 3:判断库存是否充足
        // if(num >  numstore ){ return  "商品库存不足..."; }
        // 4: 下单逻辑
        // orderService.saveOrder(order);
        // 5: 下单成功要扣减库存
        // 6: 下单完成以后
        System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
        String exchangeName = "direct_order_exchange";
        rabbitTemplate.convertAndSend(exchangeName, "email", orderNumer);
        rabbitTemplate.convertAndSend(exchangeName, "weixin", orderNumer);
    }

2.3 消费者

// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"email.direct.queue"})
@Component
public class DirectEmailService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("direct-email-------------->" + message);
    }
}
// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"sms.direct.queue"})
@Component
public class DirectSMSService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("direct-sms-------------->" + message);
    }
}
@RabbitListener(queues = {"weixin.direct.queue"})
@Component
public class DirectWeixinService {

    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("direct-weixin-------------->" + message);
    }
}

3. topic模式

Topic 交换器是 RabbitMQ 中用于更灵活的消息路由模式。它结合了 Direct 交换器的基于路由键匹配的特点,但允许使用通配符进行部分匹配。这使得 Topic 交换器非常适合于实现动态且复杂的路由逻辑。

3.1 配置类

无,采用注解的方式

3.2 生产者

    public void makeOrderTopic(Long userId, Long productId, int num) {
        // 1: 模拟用户下单
        String orderNumer = UUID.randomUUID().toString();
        // 2: 根据商品id productId 去查询商品的库存
        // int numstore = productSerivce.getProductNum(productId);
        // 3:判断库存是否充足
        // if(num >  numstore ){ return  "商品库存不足..."; }
        // 4: 下单逻辑
        // orderService.saveOrder(order);
        // 5: 下单成功要扣减库存
        // 6: 下单完成以后
        System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
        String exchangeName = "topic_order_exchange";
//        String routeKey = "jack.weixin.sss";
        String routeKey = "com.email.duanxin";
        rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
    }

3.3 消费者

// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(bindings =@QueueBinding(
        // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
        value = @Queue(value = "email.topic.queue",autoDelete = "false"),
        // order.fanout 交换机的名字 必须和生产者保持一致
        exchange = @Exchange(value = "topic_order_exchange",
                // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
                type = ExchangeTypes.TOPIC),
        key = "#.email.#"
))
@Component
public class TopicEmailService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("topic-email-------------->" + message);
    }
}
// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(bindings =@QueueBinding(
        // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
        value = @Queue(value = "sms.topic.queue",autoDelete = "false"),
        // order.fanout 交换机的名字 必须和生产者保持一致
        exchange = @Exchange(value = "topic_order_exchange",
                // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
                type = ExchangeTypes.TOPIC),
        key = "#.sms.#"
))
@Component
public class TopicSMSService {
    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("topic-sms-------------->" + message);
    }
}
@RabbitListener(bindings =@QueueBinding(
        // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
        value = @Queue(value = "weixin.topic.queue",autoDelete = "false"),
        // order.fanout 交换机的名字 必须和生产者保持一致
        exchange = @Exchange(value = "topic_order_exchange",
                // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
                type = ExchangeTypes.TOPIC),
        key = "#.weixin.#"
))
@Component
public class TopicWeixinService {

    // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
    @RabbitHandler
    public void messagerevice(String message){
        // 此处省略发邮件的逻辑
        System.out.println("topic-weixin-------------->" + message);
    }
}

4. 配置类VS注解

RabbitMQ 是一个开源的消息代理和队列服务器,用来实现应用程序之间的消息传递。在使用 RabbitMQ 时,配置类和注解是两种常见的配置方式。每种方式都有其优点和缺点。

4.1 配置类

  • 优点:
  1. 灵活性: 使用配置类可以非常灵活地定义复杂的队列、交换器、绑定等。
  2. 可重用性: 配置类可以被多个组件或服务复用。
  3. 易于管理: 当项目变得复杂时,配置类可以让配置项更加集中,易于管理和维护。
  4. 明确性: 配置类使得配置逻辑清晰可见,便于理解业务逻辑。
  5. 测试友好: 可以更容易地为配置类编写单元测试。
  • 缺点:
  1. 代码量: 相比于注解,配置类通常需要更多的代码来设置相同的配置。
  2. 学习曲线: 对于初学者来说,可能需要一些时间来掌握如何正确使用配置类进行配置。
  3. 分散注意力: 开发者需要在业务逻辑和服务配置之间切换,可能会稍微分散对主要业务的关注。

4.2 注解

优点:

  1. 简洁: 使用注解可以直接在类或方法上声明配置,减少模板代码,使代码更简洁。
  2. 快速开发: 对于简单的应用场景,注解可以帮助开发者快速完成配置,提高开发效率。
  3. 直观: 注解直接与相关的类或方法关联,使得配置意图一目了然。
  4. 集成良好: 在Spring框架中,注解方式可以很好地与Spring的其他功能(如AOP)结合使用。
    缺点:
  5. 扩展性: 当需求变更或系统规模扩大时,注解可能不足以应对复杂的配置需求。
  6. 隐式配置: 过多使用注解可能导致配置变得隐晦,不那么显而易见,这可能不利于后续的维护。
  7. 限制性: 注解提供的是预设好的配置选项,对于非标准配置支持不够灵活。
  8. 调试困难: 如果出现配置错误,注解方式可能不容易定位问题所在。

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

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

相关文章

基于springboot vue网上摄影工作室系统设计与实现

博主介绍:专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

04 面部表情识别:Pytorch实现表情识别-表情数据集训练代码

总目录:人脸检测与表情分类 https://blog.csdn.net/whiffeyf/category_12793480.html 目录 0 相关资料1 面部表情识数据集2 模型下载3 训练 0 相关资料 面部表情识别2:Pytorch实现表情识别(含表情识别数据集和训练代码):https://blog.csdn.n…

Linux系统安装和配置 VNC 服务器

文章目录 1.安装 GNOME 桌面环境2.安装 VNC 服务器(tigervnc-server)3.为本地用户设置 VNC 密码4.设置 VNC 服务器配置文件5.启动 VNC 服务并允许防火墙中的端口 1.安装 GNOME 桌面环境 [rootserver6 ~]# dnf groupinstall "workstation" -y成…

Linux——k8s组件

kubernetes 使用1.31.1 版本搭建集群核心组件,选择flannel 网络插件为整体集群的运行提供网络通信功能。 flannel 网络插件 kube-flannel kube-flannel-ds-9fgml 1/1 Running 1 (18m ago) 2d21h kube-flannel kube-flannel-ds-ghwbq …

blender设置背景图怎么添加?blender云渲染选择

Blender是一款功能强大的3D建模软件,它以流畅的操作体验和直观的用户界面而闻名。使用Blender,你可以轻松地为你的3D模型添加背景图片。 以下是具体的操作步骤: 1、启动Blender:首先,打开Blender软件。访问添加菜单&a…

jQuery——offset 和 position

获取/设置标签的位置数据 offset():相对页面左上角的坐标 position():相对于父元素左上角的坐标 本文分享到此结束,欢迎大家评论区相互讨论学习,下一篇继续分享jQuery中scroll的学…

好用的电容笔有哪些推荐?2024盘点五款高性价比平替电容笔!

近几年,平板电脑等电子设备已经成为我们学习、工作和创作的重要工具。而电容笔作为这些设备的重要配件,更是受到了广泛地欢迎。然而,苹果原装电容笔价格较高,对于很多用户来说,寻找一款高性价比的平替电容笔成为了他们…

ClickHouse | 查询

1 ALL 子句 2 ARRAY JOIN 使用别名 :在使用时可以为数组指定别名,数组元素可以通过此别名访问,但数组本身则通过原始名称访问 3 DISTINCT子句 DISTINCT不支持当包含有数组的列 4 FROM子句 FROM 子句指定从以下数据源中读取数据: 1.表 2.子…

【微服务即时通讯系统】——brpc远程过程调用、百度开源的RPC框架、brpc的介绍、brpc的安装、brpc使用和功能测试

文章目录 brpc1. brpc的介绍1.1 rpc的介绍1.2 rpc的原理1.3 grpc和brpc 2. brpc的安装3. brpc使用3.1 brpc接口介绍 4. brpc使用测试4.1 brpc同步和异步调用 brpc 1. brpc的介绍 1.1 rpc的介绍 RPC(Remote Procedure Call)远程过程调用,是一…

在线远程考试|基于springBoot的在线远程考试系统设计与实现(附项目源码+论文+数据库)

私信或留言即免费送开题报告和任务书(可指定任意题目) 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 信息数据从传统到当代,是一直在变革当中,突…

常用的cmd命令——使用bat命令创建程序的快捷方式

示例使用场景:例如便携版的软件,需要往桌面发快捷方式 如便携的浏览器,给桌面发送快捷方式,同时设置快捷方式的启动参数。 下面以谷歌浏览器为例: 浏览器的App的下级目录为如下内容 知道了所需文件的位置,…

实在智能:创业需找准“切口” 并着力做深做透

如今,随着人工智能产业的爆发,大量专注于这一领域的初创企业不断涌现。尽管这种多元化的创新生态为产业发展注入了新的活力,但也不可避免的为初创企业带来了诸多压力和挑战。 浙江实在智能科技有限公司(以下简称“实在智能”)作为一家成立6年…

近万字深入讲解iOS常见锁及线程安全

什么是锁? 在程序中,当多个任务(或线程)同时访问同一个资源时,比如多个操作同时修改一份数据,可能会导致数据不一致。这时候,我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…

文档翻译软件哪个好用?高效翻译看这里

文档翻译对打工人来说是件很头疼的事情吧?不仅是因为复杂的专业词汇,还因为不同语言之间的表达方式差异,使得翻译工作变得异常繁琐。 不过,幸运的是,现在有许多在线工具可以帮助我们轻松地翻译文档。 这些工具大多数…

【Linux】ubuntu 16.04 搭建jdk 11 环境(亲测可用)

目录 0.环境 1.题外话 2.详细 0.环境 windows11 主机 Virtual Box 7.0 ubuntu 16.04系统 想搭建个 jdk11的环境,用于项目 1.题外话 因为虚拟机与主机传输文件不方便,所以可以尝试用共享文件夹的方式传输,亲测可用,参考以下博…

C# 游戏引擎中的协程

前言 书接上回,我谈到了Unity中的协程的重要性,虽然协程不是游戏开发“必要的”,但是它可以在很多地方发挥优势。 为了在Godot找回熟悉的Unity协程开发手感,不得不自己做一个协程系统,幸运的是,有了Unity的…

探索顶级低代码开发平台,实现创新

文章盘点ZohoCreator、OutSystems等10款顶尖低代码开发平台,各平台以快速开发、集成、数据安全等为主要特点,适用于不同企业需求,助力数字化转型。 一、Zoho Creator Zoho Creator 是一个低代码开发平台,它简化了应用开发中的复杂…

PK过Google、Facebook,YouTube竟然是外贸引流营销的新前景

在如今的外贸行业中,广告投放已经成为商家吸引客户和提高销量的重要工具。众所周知,Facebook和谷歌是广告投放的两大巨头平台。这两者以其强大的用户基数和广告精准性在市场上占据主导地位。然而,随着互联网的发展和消费趋势的改变&#xff0…

MongoDB 工具包安装(mongodb-database-tools)

首先到官网下载工具包,进入下面页面,复制连接地址,使用wget下载 cd /usr/local/mongodb5.0.14/wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.6.1.tgz 安装 tar -zxvf mongodb-database-tools-rhel70-…

《北方牧业》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问:《中国动物检疫》是不是核心期刊? 答:不是,是知网收录的正规学术期刊。 问:《中国动物检疫》级别? 答:省级。主管单位:河北省畜牧局 主办单…