【RabbitMQ——SpringBoot整合】

devtools/2024/9/29 17:57:32/

1. fanout模式

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

1.1 配置类

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

1.3 消费者

// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"email.fanout.queue"})
@Component
public class FanoutEmailService {// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic void messagerevice(String message){// 此处省略发邮件的逻辑System.out.println("fanout-email-------------->" + message);}
}
// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"sms.fanout.queue"})
@Component
public class FanoutSMSService {// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic void messagerevice(String message){// 此处省略发邮件的逻辑System.out.println("fanout-sms-------------->" + message);}
}
@RabbitListener(queues = {"weixin.fanout.queue"})
@Component
public class FanoutWeixinService {// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic 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模式的交换机@Beanpublic DirectExchange directOrderExchange() {return new DirectExchange("direct_order_exchange", true, false);}// 2. 申明队列sms.fanout.queue  email.fanout.queue duanxin.fanout.queue@Beanpublic Queue directEmailQueue() {// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable// autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。//   return new Queue("TestDirectQueue",true,true,false);//一般设置一下队列的持久化就好,其余两个就是默认falsereturn new Queue("email.direct.queue", true);}@Beanpublic Queue directSmsQueue() {return new Queue("sms.direct.queue", true);}@Beanpublic Queue directWeixinQueue() {return new Queue("weixin.direct.queue", true);}// 3. 完成绑定关系@Beanpublic Binding directBindingDirect1() {return BindingBuilder.bind(directWeixinQueue()).to(directOrderExchange()).with("weixin");}@Beanpublic Binding directBindingDirect2() {return BindingBuilder.bind(directSmsQueue()).to(directOrderExchange()).with("sms");}@Beanpublic 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 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic void messagerevice(String message){// 此处省略发邮件的逻辑System.out.println("direct-email-------------->" + message);}
}
// bindings其实就是用来确定队列和交换机绑定关系
@RabbitListener(queues = {"sms.direct.queue"})
@Component
public class DirectSMSService {// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic void messagerevice(String message){// 此处省略发邮件的逻辑System.out.println("direct-sms-------------->" + message);}
}
@RabbitListener(queues = {"weixin.direct.queue"})
@Component
public class DirectWeixinService {// @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic 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 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic 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 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic 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 代表此方法是一个消息接收的方法。该不要有返回值@RabbitHandlerpublic 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.ppmy.cn/devtools/118809.html

相关文章

边缘计算网关:轻工行业的智能化新引擎

在轻工行业迈向智能化转型的浪潮中,边缘计算网关作为关键技术载体,正逐步展现其不可替代的作用。这一前沿技术,通过在数据源附近进行高效数据处理与分析,不仅加速了数据价值挖掘,还推动了生产流程的优化与效率的提升。…

c语言和c++一样吗

C语言和C并不一样,尽管它们有很多相似之处。以下是一些主要区别: 编程范式 C语言:主要是一种过程式编程语言,强调函数和过程。 C:支持面向对象编程(OOP),引入了类、对象、继承、多态…

用通义灵码如何快速合理解决遗留代码问题?

本文首先介绍了遗留代码的概念,并对遗留代码进行了分类。针对不同类型的遗留代码,提供了相应的处理策略。此外,本文重点介绍了通义灵码在维护遗留代码过程中能提供哪些支持。 什么是遗留代码 与过时技术相关的代码: 与不再受支持的…

vue3基础九问,你会几问

1. Vue是什么? Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,采用自下而上的增量开发设计,这使得你可以将 Vue 轻松地整合到现有的项目中,或者与其他前端库一起使用。Vue 的目标是通过提供反…

【习题】应用开发安全

判断题 1. TEE是Trusted execution environment的缩写: A、正确(True) B、错误(False) 2. OS Kernel(操作系统内核)的安全性要强于TEE: A、正确(True) B、错误(False) 单选题 1. 以下哪个不是HarmonyOS安全设计…

力扣题解2535

大家好,欢迎来到无限大的频道。 今日继续给大家带来每日一题的题解。 题目描述(简单): 数组元素和与数字和的绝对差 元素和 是 nums 中的所有元素相加求和。 数字和 是 nums 中每一个元素的每一数位(重复数位需多次…

HTML【知识改变命运】03font 字体标签

题目:在页面上显示"北京"两个字,字体为微软雅黑,颜色为红色,大小为40xp; font标签可以修饰字体的大小,颜色,和字体 属性:color颜色,face字体,size大…

JWT手动生成token

依赖&#xff1a; <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> …