【RabbitMQ——SpringBoot整合】

[复制链接]
发表于 2026-1-16 22:32:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1. fanout模式

Fanout 交换器(Exchange)是 RabbitMQ 中的一种消息路由模式。它是一种广播式的交换器,会将吸收到的消息发送给全部绑定到该交换器的队列,而不思量路由键(routing key)。这意味着无论消息发布时指定了什么路由键,Fanout 交换器都会忽略这些信息,并简单地将消息复制并分发给全部的绑定队列。
1.1 设置类
  1. @Configuration
  2. public class FanoutRabbitConfig {
  3.     // 1. 声明注册fanout模式的交换机
  4.     @Bean
  5.     public FanoutExchange fanoutOrderExchange() {
  6.         //  return new DirectExchange("TestDirectExchange",true,true);
  7.         return new FanoutExchange("fanout_order_exchange", true, false);
  8.     }
  9.     // 2. 申明队列sms.fanout.queue  email.fanout.queue duanxin.fanout.queue
  10.     @Bean
  11.     public Queue fanoutEmailQueue() {
  12.         // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
  13.         // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
  14.         // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
  15.         //   return new Queue("TestDirectQueue",true,true,false);
  16.         //一般设置一下队列的持久化就好,其余两个就是默认false
  17.         return new Queue("email.fanout.queue", true);
  18.     }
  19.     @Bean
  20.     public Queue fanoutSmsQueue() {
  21.         return new Queue("sms.fanout.queue", true);
  22.     }
  23.     @Bean
  24.     public Queue fanoutWeixinQueue() {
  25.         return new Queue("weixin.fanout.queue", true);
  26.     }
  27.     // 3. 完成绑定关系
  28.     @Bean
  29.     public Binding fanoutBindingDirect1() {
  30.         return BindingBuilder.bind(fanoutEmailQueue()).to(fanoutOrderExchange());
  31.     }
  32.     @Bean
  33.     public Binding fanoutBindingDirect2() {
  34.         return BindingBuilder.bind(fanoutSmsQueue()).to(fanoutOrderExchange());
  35.     }
  36.     @Bean
  37.     public Binding fanoutBindingDirect3() {
  38.         return BindingBuilder.bind(fanoutWeixinQueue()).to(fanoutOrderExchange());
  39.     }
  40. }
复制代码
1.2 生产者
  1. public void makeOrder(Long userId, Long productId, int num) {
  2.     // 1: 模拟用户下单
  3.     String orderNumer = UUID.randomUUID().toString();
  4.     // 2: 根据商品id productId 去查询商品的库存
  5.     // int numstore = productSerivce.getProductNum(productId);
  6.     // 3:判断库存是否充足
  7.     // if(num >  numstore ){ return  "商品库存不足..."; }
  8.     // 4: 下单逻辑
  9.     // orderService.saveOrder(order);
  10.     // 5: 下单成功要扣减库存
  11.     // 6: 下单完成以后
  12.     System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
  13.     // 发送订单信息给RabbitMQ fanout
  14.     String exchangeName = "fanout_order_exchange";
  15.     String routeKey = "";
  16.     rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
  17. }
复制代码
1.3 斲丧者
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(queues = {"email.fanout.queue"})
  3. @Component
  4. public class FanoutEmailService {
  5.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  6.     @RabbitHandler
  7.     public void messagerevice(String message){
  8.         // 此处省略发邮件的逻辑
  9.         System.out.println("fanout-email-------------->" + message);
  10.     }
  11. }
复制代码
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(queues = {"sms.fanout.queue"})
  3. @Component
  4. public class FanoutSMSService {
  5.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  6.     @RabbitHandler
  7.     public void messagerevice(String message){
  8.         // 此处省略发邮件的逻辑
  9.         System.out.println("fanout-sms-------------->" + message);
  10.     }
  11. }
复制代码
  1. @RabbitListener(queues = {"weixin.fanout.queue"})
  2. @Component
  3. public class FanoutWeixinService {
  4.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  5.     @RabbitHandler
  6.     public void messagerevice(String message){
  7.         // 此处省略发邮件的逻辑
  8.         System.out.println("fanout-weixin-------------->" + message);
  9.     }
  10. }
复制代码
2. direct模式

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

留意设置类中声明的交换机的范例,以及队列携带的路由key
  1. @Configuration
  2. public class DirectRabbitConfig {
  3.     // 1. 声明注册fanout模式的交换机
  4.     @Bean
  5.     public DirectExchange directOrderExchange() {
  6.         return new DirectExchange("direct_order_exchange", true, false);
  7.     }
  8.     // 2. 申明队列sms.fanout.queue  email.fanout.queue duanxin.fanout.queue
  9.     @Bean
  10.     public Queue directEmailQueue() {
  11.         // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
  12.         // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
  13.         // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
  14.         //   return new Queue("TestDirectQueue",true,true,false);
  15.         //一般设置一下队列的持久化就好,其余两个就是默认false
  16.         return new Queue("email.direct.queue", true);
  17.     }
  18.     @Bean
  19.     public Queue directSmsQueue() {
  20.         return new Queue("sms.direct.queue", true);
  21.     }
  22.     @Bean
  23.     public Queue directWeixinQueue() {
  24.         return new Queue("weixin.direct.queue", true);
  25.     }
  26.     // 3. 完成绑定关系
  27.     @Bean
  28.     public Binding directBindingDirect1() {
  29.         return BindingBuilder.bind(directWeixinQueue()).to(directOrderExchange()).with("weixin");
  30.     }
  31.     @Bean
  32.     public Binding directBindingDirect2() {
  33.         return BindingBuilder.bind(directSmsQueue()).to(directOrderExchange()).with("sms");
  34.     }
  35.     @Bean
  36.     public Binding directBindingDirect3() {
  37.         return BindingBuilder.bind(directEmailQueue()).to(directOrderExchange()).with("email");
  38.     }
  39. }
复制代码
2.2 生产者
  1.     public void makeOrderDirect(Long userId, Long productId, int num) {
  2.         // 1: 模拟用户下单
  3.         String orderNumer = UUID.randomUUID().toString();
  4.         // 2: 根据商品id productId 去查询商品的库存
  5.         // int numstore = productSerivce.getProductNum(productId);
  6.         // 3:判断库存是否充足
  7.         // if(num >  numstore ){ return  "商品库存不足..."; }
  8.         // 4: 下单逻辑
  9.         // orderService.saveOrder(order);
  10.         // 5: 下单成功要扣减库存
  11.         // 6: 下单完成以后
  12.         System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
  13.         String exchangeName = "direct_order_exchange";
  14.         rabbitTemplate.convertAndSend(exchangeName, "email", orderNumer);
  15.         rabbitTemplate.convertAndSend(exchangeName, "weixin", orderNumer);
  16.     }
复制代码
2.3 斲丧者
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(queues = {"email.direct.queue"})
  3. @Component
  4. public class DirectEmailService {
  5.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  6.     @RabbitHandler
  7.     public void messagerevice(String message){
  8.         // 此处省略发邮件的逻辑
  9.         System.out.println("direct-email-------------->" + message);
  10.     }
  11. }
复制代码
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(queues = {"sms.direct.queue"})
  3. @Component
  4. public class DirectSMSService {
  5.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  6.     @RabbitHandler
  7.     public void messagerevice(String message){
  8.         // 此处省略发邮件的逻辑
  9.         System.out.println("direct-sms-------------->" + message);
  10.     }
  11. }
复制代码
  1. @RabbitListener(queues = {"weixin.direct.queue"})
  2. @Component
  3. public class DirectWeixinService {
  4.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  5.     @RabbitHandler
  6.     public void messagerevice(String message){
  7.         // 此处省略发邮件的逻辑
  8.         System.out.println("direct-weixin-------------->" + message);
  9.     }
  10. }
复制代码
3. topic模式

Topic 交换器是 RabbitMQ 中用于更机动的消息路由模式。它连合了 Direct 交换器的基于路由键匹配的特点,但允许利用通配符举行部门匹配。这使得 Topic 交换器非常适当于实现动态且复杂的路由逻辑。
3.1 设置类

无,采取注解的方式
3.2 生产者
  1.     public void makeOrderTopic(Long userId, Long productId, int num) {
  2.         // 1: 模拟用户下单
  3.         String orderNumer = UUID.randomUUID().toString();
  4.         // 2: 根据商品id productId 去查询商品的库存
  5.         // int numstore = productSerivce.getProductNum(productId);
  6.         // 3:判断库存是否充足
  7.         // if(num >  numstore ){ return  "商品库存不足..."; }
  8.         // 4: 下单逻辑
  9.         // orderService.saveOrder(order);
  10.         // 5: 下单成功要扣减库存
  11.         // 6: 下单完成以后
  12.         System.out.println("用户 " + userId + ",订单编号是:" + orderNumer);
  13.         String exchangeName = "topic_order_exchange";
  14. //        String routeKey = "jack.weixin.sss";
  15.         String routeKey = "com.email.duanxin";
  16.         rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
  17.     }
复制代码
3.3 斲丧者
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(bindings =@QueueBinding(
  3.         // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
  4.         value = @Queue(value = "email.topic.queue",autoDelete = "false"),
  5.         // order.fanout 交换机的名字 必须和生产者保持一致
  6.         exchange = @Exchange(value = "topic_order_exchange",
  7.                 // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
  8.                 type = ExchangeTypes.TOPIC),
  9.         key = "#.email.#"
  10. ))
  11. @Component
  12. public class TopicEmailService {
  13.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  14.     @RabbitHandler
  15.     public void messagerevice(String message){
  16.         // 此处省略发邮件的逻辑
  17.         System.out.println("topic-email-------------->" + message);
  18.     }
  19. }
复制代码
  1. // bindings其实就是用来确定队列和交换机绑定关系
  2. @RabbitListener(bindings =@QueueBinding(
  3.         // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
  4.         value = @Queue(value = "sms.topic.queue",autoDelete = "false"),
  5.         // order.fanout 交换机的名字 必须和生产者保持一致
  6.         exchange = @Exchange(value = "topic_order_exchange",
  7.                 // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
  8.                 type = ExchangeTypes.TOPIC),
  9.         key = "#.sms.#"
  10. ))
  11. @Component
  12. public class TopicSMSService {
  13.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  14.     @RabbitHandler
  15.     public void messagerevice(String message){
  16.         // 此处省略发邮件的逻辑
  17.         System.out.println("topic-sms-------------->" + message);
  18.     }
  19. }
复制代码
  1. @RabbitListener(bindings =@QueueBinding(
  2.         // email.fanout.queue 是队列名字,这个名字你可以自定随便定义。
  3.         value = @Queue(value = "weixin.topic.queue",autoDelete = "false"),
  4.         // order.fanout 交换机的名字 必须和生产者保持一致
  5.         exchange = @Exchange(value = "topic_order_exchange",
  6.                 // 这里是确定的rabbitmq模式是:fanout 是以广播模式 、 发布订阅模式
  7.                 type = ExchangeTypes.TOPIC),
  8.         key = "#.weixin.#"
  9. ))
  10. @Component
  11. public class TopicWeixinService {
  12.     // @RabbitHandler 代表此方法是一个消息接收的方法。该不要有返回值
  13.     @RabbitHandler
  14.     public void messagerevice(String message){
  15.         // 此处省略发邮件的逻辑
  16.         System.out.println("topic-weixin-------------->" + message);
  17.     }
  18. }
复制代码
4. 设置类VS注解

RabbitMQ 是一个开源的消息署理和队列服务器,用来实现应用步调之间的消息转达。在利用 RabbitMQ 时,设置类和注解是两种常见的设置方式。每种方式都有其长处和缺点。
4.1 设置类


  • 长处:

  • 机动性: 利用设置类可以非常机动地界说复杂的队列、交换器、绑定等。
  • 可重用性: 设置类可以被多个组件或服务复用。
  • 易于管理: 当项目变得复杂时,设置类可以让设置项更加会合,易于管理和维护。
  • 明白性: 设置类使得设置逻辑清楚可见,便于明白业务逻辑。
  • 测试友爱: 可以更容易地为设置类编写单位测试。


  • 缺点:

  • 代码量: 相比于注解,设置类通常须要更多的代码来设置雷同的设置。
  • 学习曲线: 对于初学者来说,大概须要一些时间来把握怎样精确利用设置类举行设置。
  • 分散留意力: 开发者须要在业务逻辑和服务设置之间切换,大概会轻微分散对告急业务的关注。
4.2 注解

长处:

  • 轻便: 利用注解可以直接在类或方法上声明设置,淘汰模板代码,使代码更轻便。
  • 快速开发: 对于简单的应用场景,注解可以资助开发者快速完成设置,进步开发服从。
  • 直观: 注解直接与干系的类或方法关联,使得设置意图一览无余。
  • 集成精良: 在Spring框架中,注解方式可以很好地与Spring的其他功能(如AOP)连合利用。
    缺点:
  • 扩展性: 当需求变更或体系规模扩大时,注解大概不敷以应对复杂的设置需求。
  • 隐式设置: 过多利用注解大概导致设置变得隐晦,不那么显而易见,这大概倒霉于后续的维护。
  • 限定性: 注解提供的是预设好的设置选项,对于非尺度设置支持不敷机动。
  • 调试困难: 假如出现设置错误,注解方式大概不容易定位题目所在。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表