前言
在做点评项目的过程中遇到了异步通信的问题,只是项目中是基于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 主要核心组件
- AmqpTemplate / RabbitTemplate
- 用于发送和接收消息。
- 类似于 JMS 中的 JmsTemplate。
- 支持同步发送、异步发送、请求-响应模式
java
rabbitTemplate.convertAndSend("exchangeName", "routingKey", message);
- MessageConverter
- 负责 Java 对象与 AMQP 消息之间的转换。
- 默认使用 SimpleMessageConverter(仅支持 String、byte[]、Serializable)。
- 常用替代:Jackson2JsonMessageConverter(支持 JSON 序列化对象)。
- @RabbitListener
声明式消费消息,类似 @JmsListener。
自动注册监听器到容器中。
java
@RabbitListener(queues = "myQueue")
public void handleMessage(MyMessage msg) {
// 处理消息
}
- RabbitListenerContainerFactory
- 用于创建监听器容器(如 SimpleMessageListenerContainer)。
- 可配置并发消费者数、确认模式(acknowledge mode)、错误处理等
1.3 简单来讲📦 Spring AMQP 就是把下面图像中的过程用简单的代码实现了

- 连 RabbitMQ:不用自己写连接代码。
- 发消息:一行代码就能把"订单"发到交换机再有交换机转发到队列
java
rabbitTemplate.convertAndSend("交换机名字","订单队列Key", "要发送的信息");
- 收消息:加个注解,自动监听队列并处理。
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 + "】");
}
小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)
。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。