RabbitMQ(RabbitMQ的消息收发的模板工具:SpringAMQP)

前言

在做点评项目的过程中遇到了异步通信的问题,只是项目中是基于Redis实现的,最近也是准备投简历了,看了好多,发现大多数都是基于RabbitMQ实现的,来花个几个小时专门学习一下吧(我是跟着黑马程序员的课学的,大家也可以去看看视频)

目录

    • 前言
    • [1. 什么是SpringAMQP?🤔](#1. 什么是SpringAMQP?🤔)
      • [1.1 SpringAMQP提供了三个功能:](#1.1 SpringAMQP提供了三个功能:)
      • [1.2 主要核心组件](#1.2 主要核心组件)
      • [1.3 简单来讲📦 Spring AMQP 就是把下面图像中的过程用简单的代码实现了](#1.3 简单来讲📦 Spring AMQP 就是把下面图像中的过程用简单的代码实现了)
  • [2.下面来更深入的学习Spring AMQP帮助RabbitMQ收发消息的方式](#2.下面来更深入的学习Spring AMQP帮助RabbitMQ收发消息的方式)
    • 2.1:声明队列和交换机:
      • 2.1.1交换机的类型有四种:
      • 拓展🧩:
        • [1. Fanout Exchange(扇出交换机)🔊 广播专用!](#1. Fanout Exchange(扇出交换机)🔊 广播专用!)
        • [2. Direct Exchange(直连交换机)✅ 最常用!](#2. Direct Exchange(直连交换机)✅ 最常用!)
      • [2.1.2 Topic Exchange(主题交换机)🔍 最灵活!](#2.1.2 Topic Exchange(主题交换机)🔍 最灵活!)
      • [2.1.3 声明一个fanout类型的交换机](#2.1.3 声明一个fanout类型的交换机)
      • [2.1.4 声明一个Direct类型的交换机](#2.1.4 声明一个Direct类型的交换机)
      • 基于注解声明
    • [2.2 消息的接收和发送:](#2.2 消息的接收和发送:)
      • [2.2.1 Fanout交换机:](#2.2.1 Fanout交换机:)
      • [2.2.2 Direct交换机:](#2.2.2 Direct交换机:)
      • [2.2.3 Topic交换机:](#2.2.3 Topic交换机:)

1. 什么是SpringAMQP?🤔

前面讲了在RabbitMQ控制台操作收发消息,我们开发业务功能的时候,肯定不能这样,应该基于编程的方式

但RabbitMQ官方提供的Java客户端编码相对复杂 ,而Spring的官方刚好基于RabbitMQ提供了这样一套消息收发的模板工具:SpringAMQP

1.1 SpringAMQP提供了三个功能:

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

1.2 主要核心组件

  1. AmqpTemplate / RabbitTemplate
  • 用于发送和接收消息。
  • 类似于 JMS 中的 JmsTemplate。
  • 支持同步发送、异步发送、请求-响应模式
java 复制代码
rabbitTemplate.convertAndSend("exchangeName", "routingKey", message);
  1. MessageConverter
  • 负责 Java 对象与 AMQP 消息之间的转换。
  • 默认使用 SimpleMessageConverter(仅支持 String、byte[]、Serializable)。
  • 常用替代:Jackson2JsonMessageConverter(支持 JSON 序列化对象)。
  1. @RabbitListener
    声明式消费消息,类似 @JmsListener。
    自动注册监听器到容器中。
java 复制代码
@RabbitListener(queues = "myQueue")
public void handleMessage(MyMessage msg) {
    // 处理消息
}
  1. RabbitListenerContainerFactory
  • 用于创建监听器容器(如 SimpleMessageListenerContainer)。
  • 可配置并发消费者数、确认模式(acknowledge mode)、错误处理等

1.3 简单来讲📦 Spring AMQP 就是把下面图像中的过程用简单的代码实现了

  1. 连 RabbitMQ:不用自己写连接代码。
  2. 发消息:一行代码就能把"订单"发到交换机再有交换机转发到队列
java 复制代码
rabbitTemplate.convertAndSend("交换机名字","订单队列Key", "要发送的信息");
  1. 收消息:加个注解,自动监听队列并处理。
java 复制代码
@RabbitListener(queues = "订单队列")
public void handleOrder(String message) {
    System.out.println("收到订单:" + message);
}

SpringAMQP在发消息时要选择交换机,不同的交换机发消息的方式也不一样

2.下面来更深入的学习Spring AMQP帮助RabbitMQ收发消息的方式

要发送消息肯定要有交换机和队列:

2.1:声明队列和交换机:

2.1.1交换机的类型有四种:

  • Fanout:广播,将消息交给所有绑定到交换机的队列。我们最早在控制台使用的正是Fanout交换机
  • Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列
  • Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符
  • Headers:头匹配,基于MQ的消息头匹配,用的较少。

拓展🧩:

1. Fanout Exchange(扇出交换机)🔊 广播专用!
  • 规则:只要队列绑定了这个交换机,就全部收到。
  • 特点:真正的"广播",速度最快(无需匹配)。

🌰 例子:

2. Direct Exchange(直连交换机)✅ 最常用!

规则:Routing Key 必须完全等于 绑定时指定的 key。

特点:一对一 or 一对多(多个队列用相同 key 绑定,可实现广播 )。

🌰 例子

注⚠️: Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

2.1.2 Topic Exchange(主题交换机)🔍 最灵活!

  • 规则:Routing Key 是 点分字符串(如 "user.login.cn"),绑定时可用通配符:
    *:匹配一个单词(不能跨点)
    #:匹配零个或多个单词(可跨点)

🌰 通配符示例:

Routing Key 是否匹配*.login.* 是否匹配 user.#
user.login.cn ✅ 是 ✅ 是
admin.login.us ✅ 是 ❌ 否(不是 user 开头
user.action.view ❌ 否 ✅ 是

⚠️注:Exchange(交换机)只负责转发消息,不具备存储消息的能力

2.1.3 声明一个fanout类型的交换机

java 复制代码
package com.itheima.consumer.config;

import ...

@Configuration
public class FanoutConfig {
    /**
     * 声明交换机
     * @return Fanout类型交换机
     */
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("hmall.fanout");
    }

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

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

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

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

2.1.4 声明一个Direct类型的交换机

java 复制代码
@Configuration
public class RabbitConfig {

    // 1. 声明一个队列
    @Bean
    public Queue orderQueue() {
        return new Queue("order.queue", true); // true = 持久化(重启不丢)
    }

    // 2. 声明一个 Direct 类型的交换机
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange("order.exchange");
    }

    // 3. 把队列绑定到交换机,用 routing key "create.order"
    @Bean
    public Binding orderBinding() {
        return BindingBuilder
                .bind(orderQueue())
                .to(orderExchange())
                .with("create.order");
    }
}

基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式来声明

基于注解声明

java 复制代码
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
    System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue2"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
    System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue1"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "china.#"
))
public void listenTopicQueue1(String msg){
    System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "topic.queue2"),
    exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),
    key = "#.news"
))
public void listenTopicQueue2(String msg){
    System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}

2.2 消息的接收和发送:

2.2.1 Fanout交换机:

消息发送

java 复制代码
@Test
public void testFanoutExchange() {
    // 交换机名称
    String exchangeName = "hmall.fanout";
    // 消息
    String message = "hello, everyone!";
    rabbitTemplate.convertAndSend(exchangeName, "", message);
}

消息接收

java 复制代码
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {
    System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}

@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {
    System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}

2.2.2 Direct交换机:

接受消息:

java 复制代码
@RabbitListener(queues = "direct.queue1")
public void listenDirectQueue1(String msg) {
    System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}

@RabbitListener(queues = "direct.queue2")
public void listenDirectQueue2(String msg) {
    System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

消息发送:

java 复制代码
@Test
public void testSendDirectExchange() {
    // 交换机名称
    String exchangeName = "hmall.direct";
    // 消息
    String message = "红红火火";
    // 发送消息
    rabbitTemplate.convertAndSend(exchangeName, "red", message);
}

2.2.3 Topic交换机:

消息发送

java 复制代码
/**
 * topicExchange
 */
@Test
public void testSendTopicExchange() {
    // 交换机名称
    String exchangeName = "hmall.topic";
    // 消息
    String message = "hhhhhhhhhhh";
    // 发送消息
    rabbitTemplate.convertAndSend(exchangeName, "china.news", message);
}

消息接收

java 复制代码
@RabbitListener(queues = "topic.queue1")
public void listenTopicQueue1(String msg){
    System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}

@RabbitListener(queues = "topic.queue2")
public void listenTopicQueue2(String msg){
    System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}

小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。

相关推荐
听风吟丶1 小时前
分布式追踪实战:SkyWalking 构建微服务全链路可观测性体系
分布式·微服务·skywalking
华大哥2 小时前
linux 安装Kafka 和springboot kaka实战
分布式·kafka·springboot
沧海寄馀生2 小时前
Apache Hadoop生态组件部署分享-Sqoop
大数据·hadoop·分布式·apache·sqoop
脸大是真的好~2 小时前
尚硅谷-Kafka01-介绍-安装-ZK和Broker工具-Kafka系统架构-启动和竞争管理者controller
分布式·kafka·系统架构
沧海寄馀生2 小时前
Apache Hadoop生态组件部署分享-Ranger
大数据·hadoop·分布式·apache
嘻哈baby14 小时前
接口幂等性设计实战|防止重复提交的几种方案
分布式·环境测试
shaohaoyongchuang18 小时前
02-nacos入门
分布式·微服务
鹿衔`18 小时前
CDH 6.3.2 集群外挂部署 Spark 3.5.7 连接 Paimon 1.1.1 (二)
大数据·分布式·spark
CrazyClaz20 小时前
分布式事务专题3
分布式·分布式事务