什么是rabbitmq
RabbitMQ是一个开源的消息队列系统,它实现了高级消息队列协议(AMQP)。AMQP是一种网络协议,它支持符合要求的客户端应用程序之间的消息传递。RabbitMQ是用Erlang编写的,它是一种适用于并发系统的编程语言,这使得RabbitMQ能够在多种平台上提供高可靠性和高效性能。
核心概念
- 消息(Messages):在RabbitMQ中,消息是传输的单位,它由一些可用的属性和消息体组成。
- 生产者(Producers):发送消息的应用程序通常称为生产者。
- 队列(Queues):用于存储消息的数据结构。消息在被消费之前会一直存储在队列中。
- 交换器(Exchanges):生产者将消息发送到交换器,而不是直接发送到队列。交换器负责根据路由键(routing key)将消息路由到一个或多个队列中。
- 绑定(Bindings):绑定是交换器和队列之间的关系,它定义了交换器如何将消息路由到特定的队列。
- 虚拟主机(Virtual Hosts):RabbitMQ允许你创建多个虚拟主机,每个虚拟主机都有自己的交换器、队列和绑定。这允许在单个RabbitMQ服务器上隔离不同的应用程序和环境。
- 消费者(Consumers):从队列中接收消息的应用程序通常称为消费者。
特点和优势
- 可靠性:RabbitMQ支持消息的持久化、事务和消息确认机制,确保消息不会丢失。
- 灵活的路由:通过交换器和绑定,RabbitMQ提供了灵活的消息路由能力。
- 高可用性:RabbitMQ支持集群模式,可以提供高可用性。
- 扩展性:RabbitMQ可以根据需要轻松扩展,支持更多的生产者和消费者。
- 多种客户端支持:RabbitMQ有多种编程语言的客户端库,如Python、Java、Ruby、PHP等。
- 管理界面:RabbitMQ提供了一个易于使用的管理界面,可以用于管理和监控消息队列系统。
RabbitMQ广泛应用于各种场景,包括异步处理、应用解耦、负载均衡、分布式系统间的消息传递等。它的这些特性和优势使得RabbitMQ成为构建分布式、可靠消息传递系统的流行选择。
rabbitmq的安装 - mac
使用brew安装
brew update
brew install rabbitmq
配置环境变量
在你的shell配置文件中添加如下代码,我的是os12系统,默认为zsh
终端根目录输入 vi .zshrc 编辑添加
注意:你的版本不一定是 3.13.1,通过输入brew list rabbitmq获取到对应的文件夹地址
export RABBIT_HOME=/opt/homebrew/Cellar/rabbitmq/3.13.1
export PATH=$PATH:$RABBIT_HOME/sbin
启用插件
启用rabbitmq management插件,用于开启浏览器后台页面
sudo rabbitmq-plugins enable rabbitmq_management
启动和停止
brew services list查看 brew 管理的服务状态等brew services start rabbitmq启动brew services stop rabbitmq停止
配置用户
不配置用户远程连接是不被允许的,在开启rabbit后执行
命令行添加
# 添加用户
rabbitmqctl add_user admin password
# 设置为管理员
rabbitmqctl set_user_tags admin administrator
在管理页面添加(先执行下一步之后)
访问可视化监控插件的界面
浏览器内输入 http://localhost:15672, 默认的用户名密码都是 guest
经过上方设置后 账号为 admin 密码为 password
为虚拟主机配置用户
向下滚动找到对应用户添加(这里是刚刚创建的用户)
一些命令
rabbitmqctl stop停止rabbitmq-plugins list插件列表rabbitmq-plugins enable management启用插件rabbitmq-plugins disable xxx卸载插件
启动时可能的问题
通过日志查看 /opt/homebrew/var/log/rabbitmq/ 辨别问题
eacces
问题
error:{badmatch,{error,{{shutdown,{failed_to_start_child,auth,{"Error when reading /Users/xxxx/.erlang.cookie: eacces"
如果出现如上报错,这通常是由于权限问题(eacces 表示“权限被拒绝”)。
解决方式
- 检查 Erlang cookie 文件的权限: 确保您的用户帐户有权访问和读取这个文件。您可以使用以下命令来检查和修改文件权限:
ls -l /Users/xxx/.erlang.cookie
chmod 600 /Users/xxx/.erlang.cookie
- 检查文件所有者: 确保 Erlang cookie 文件属于启动 RabbitMQ 的用户。如果不是,您可以使用 chown 命令来更改文件所有者:
chown xxx /Users/xxx/.erlang.cookie
- 确保 RabbitMQ 服务使用正确的用户运行。
- 重启 RabbitMQ 服务: 在修改了权限之后,尝试重新启动 RabbitMQ 服务
java中的简单使用
发送
/**
* 描述: Hello World 的发送类,连接到RabbitMQ服务端,然后发送一条消息,然后退出。
*/
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ地址
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
//建立连接
Connection connection = factory.newConnection();
//获得信道
Channel channel = connection.createChannel();
/**
* 声明一个队列。
*
* @param queue 队列名称。如果为空,服务器将自动生成一个唯一名称。
* @param durable 是否持久化。如果为true,队列将在服务器重启后仍然存在。
* @param exclusive 是否排他。如果为true,队列仅能被当前连接访问,
* 并且在连接关闭时会被删除。
* @param autoDelete 是否自动删除。如果为true,当队列不再使用(没有消费者和没有消息)时,队列将被删除。
* @param arguments 队列声明的其他可选参数。这些参数取决于服务器的配置,
* 例如消息的TTL(生存时间)、死信队列设置等。
* @return 服务器返回的Queue.DeclareOk响应,其中包含队列的名称(当队列名称为空时尤为有用)。
* @throws IOException 如果在声明队列时发生错误。
*/
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//发布消息
String message = "Hello World 2!";
/**
* 发布消息到指定的交换机。
*
* @param exchange 交换机名称。不能为空,除非使用的是默认交换机。
* @param routingKey 路由键。用于决定消息应该被投递到哪个队列,或者被哪些队列绑定接收。
* @param props 消息的属性。可以设置消息的持久性、优先级、过期时间等。
* 如果需要消息持久化,需要将DeliveryMode设置为2。
* @param body 消息体。实际要发送的数据,通常是字节数组形式。
* @throws IOException 如果在发送消息过程中发生错误。
* @throws TimeoutException 如果消息发送超时。
*/
channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println("发送了消息:" + message);
//关闭连接
channel.close();
connection.close();
}
}
接收
/**
* 描述: 接收消息,并打印,持续运行
*/
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ地址
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
//建立连接
Connection connection = factory.newConnection();
//获得信道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
/**
* 接收消息并消费
* 启动一个消费者,并返回服务端生成的消费者标识
* queue:队列名
* autoAck:true 接收到传递过来的消息后acknowledged(应答服务器),false 接收到消息后不应答服务器
* deliverCallback: 当一个消息发送过来后的回调接口
* cancelCallback:当一个消费者取消订阅时的回调接口;取消消费者订阅队列时除了使用{@link Channel#basicCancel}之外的所有方式都会调用该回调方法
* @return 服务端生成的消费者标识
*/
channel.basicConsume(QUEUE_NAME, true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("收到消息:" + message);
}
});
}
}
多个消费者的接收
发送
/**
* 描述: 任务有所耗时,多个任务
*/
public class NewTask {
private final static String TASK_QUEUE_NAME = "task_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ地址
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
//建立连接
Connection connection = factory.newConnection();
//获得信道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
for (int i = 0; i < 10; i++) {
String message;
if (i % 2 == 0) {
message = i + "...";
} else {
message = String.valueOf(i);
}
channel.basicPublish("", TASK_QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println("发送了消息:" + message);
}
channel.close();
connection.close();
}
}
接收
/**
* 描述: 消费者,接收前面的批量消息
*/
public class Worker {
private final static String TASK_QUEUE_NAME = "task_queue";
//当启动多个的时候,如channel.basicConsume中的autoAck参数设置为自动消费(ture),
//那么消息会被均匀分配,当3条消息被3个消费者接收,那么就是一人接一条。
//此时并不是公平派遣(不在意任务的执行时间),只是按顺序分配给不同的消费者。
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ地址
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
//建立连接
Connection connection = factory.newConnection();
//获得信道
final Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
System.out.println("开始接收消息");
//公平派遣设置:希望处理的数量
channel.basicQos(1);
//公平派遣设置:第二个参数 非自动处理消息改为了false,注意下面一定要手动告诉消息已经处理完成
channel.basicConsume(TASK_QUEUE_NAME, false, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("收到了消息:" + message);
try {
doWork(message);
} finally {
System.out.println("消息处理完成");
//公平派遣设置:表示消息处理完成
//之后在有新消息时候,检查谁没完成,再把消息给完成了的消费者处理
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
});
}
private static void doWork(String task) {
char[] chars = task.toCharArray();
for (char ch : chars) {
//NODE:有“.”的就等等处理,好区分。
if (ch == '.') {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
交换机模式&演示
RabbitMQ有四种交换机类型,分别是:Fanout exchange、Direct exchange、Topic exchange、Headers exchange
Fanout Exchange—扇出类型交换机
只需要简单的将队列绑定到该类型交换机上,该类型的交换机绑定队列时可以不指定路由键
当消息发送给该交换机后,它会将消息投递给与该交换机绑定的所有队列
很像广播,每台子网内的机器都会获得一份消息,Fanout交换机转发消息是最快的
发送
/**
* EmitLog 类用于演示如何向 RabbitMQ 发送日志信息。
* 主要功能是创建一个连接到 RabbitMQ 服务器的客户端,声明一个交换器,然后向该交换器发布消息。
*/
public class EmitLog {
// 定义要使用的交换器名称
private static final String EXCHANGE_NAME = "logs";
/**
* 程序的主入口函数。
* @param args 命令行参数(未使用)
* @throws IOException 如果发生 I/O 错误
* @throws TimeoutException 如果连接或通道操作超时
*/
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂并配置连接到 RabbitMQ 服务器的参数
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
// 建立与 RabbitMQ 服务器的连接
Connection connection = factory.newConnection();
// 创建一个新的通道
Channel channel = connection.createChannel();
// 声明一个交换器,使用内置的 FANOUT 类型,用于广播消息
// 所有的消费者都可以收到,但是已经广播过的不会接收到。
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
// 准备要发送的消息内容
String message = "info: Hello World!";
// 向声明的交换器发布消息
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
System.out.println("发送了消息:" + message);
// 关闭通道和连接,释放资源
channel.close();
connection.close();
}
}
接收
/**
* 这个类用于接收日志消息。
* 它创建一个与RabbitMQ服务器的连接,并定义一个交换器来路由消息到队列中,
* 然后从队列中消费消息。
*/
public class ReceiveLogs {
private static final String EXCHANGE_NAME = "logs"; // 定义交换器的名称
/**
* 主函数:设置并连接到RabbitMQ服务器,声明交换器和队列,绑定队列到交换器,
* 并开始接收和处理消息。
*
* @param args 命令行参数(未使用)
* @throws IOException 如果发生I/O错误
* @throws TimeoutException 如果连接超时
*/
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂并设置RabbitMQ服务器的主机地址、用户名和密码
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
// 建立与RabbitMQ服务器的连接
Connection connection = factory.newConnection();
// 创建通道
Channel channel = connection.createChannel();
// 声明一个风扇型交换器
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
// 声明一个队列,并返回队列名称,非持久的,非自动删除的队列,可以多次启动
String queueName = channel.queueDeclare().getQueue();
// 将队列绑定到交换器上
channel.queueBind(queueName, EXCHANGE_NAME, "");
System.out.println("开始接收消息");
// 定义一个消息消费者并消费消息
Consumer consumer = new DefaultConsumer(channel) {
/**
* 当有消息到达时处理消息。
*
* @param consumerTag 消费者的标签
* @param envelope 消息的环境信息,包括消息ID等
* @param properties 消息的属性
* @param body 消息体
* @throws IOException 如果处理消息时发生I/O错误
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// 将消息体从字节转换为字符串并打印出来
String message = new String(body, "UTF-8");
System.out.println("收到消息:" + message);
}
};
// 开始消费队列中的消息
channel.basicConsume(queueName, true, consumer);
}
}
Direct exchange—直接类型交换机
要求消息带的路由键和绑定的路由键完全匹配,这是一个完整的匹配。
比如一个队列A绑定到该交换机上的路由键是“abc”,则只有指定的路由键是“abc”的消息才被投递给队列A,其他的不会投递给队列A
发送
/**
* 直接路由日志的示例类。
* 此类用于演示如何通过RabbitMQ发送不同级别的日志消息。
*/
public class EmitLogDirect {
// 定义一个直接交换机的名称
private static final String EXCHANGE_NAME = "direct_logs";
/**
* 主函数:创建连接到RabbitMQ服务器,声明交换机,并发布消息到交换机。
*
* @param args 命令行参数(未使用)
* @throws IOException 如果发生I/O错误
* @throws TimeoutException 如果连接超时
*/
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂,用于生产连接到RabbitMQ服务器
ConnectionFactory factory = new ConnectionFactory();
// 设置连接工厂要连接的主机地址
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
// 建立一个新的连接
Connection connection = factory.newConnection();
// 创建一个新的通道
Channel channel = connection.createChannel();
// 声明一个直接类型的交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
// 准备发送的消息
String message = "info:Hello World!";
// 向交换机发送消息,消息路由键为"info"
channel.basicPublish(EXCHANGE_NAME, "info", null, message.getBytes("UTF-8"));
System.out.println("发送了消息," + "等级为info,消息内容:" + message);
// 改变消息内容,然后发送到交换机,此次使用"warning"作为路由键
message = "warning:Hello World!";
channel.basicPublish(EXCHANGE_NAME, "warning", null, message.getBytes("UTF-8"));
System.out.println("发送了消息," + "等级为warning,消息内容:" + message);
// 再次改变消息内容,发送到交换机,使用"error"作为路由键
message = "error:Hello World!";
channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes("UTF-8"));
System.out.println("发送了消息," + "等级为error,消息内容:" + message);
// 关闭通道和连接以释放资源
channel.close();
connection.close();
}
}
接收不同等级的消息
/**
* 描述: 接收3个等级的日志
*/
public class ReceiveLogsDirect1 {
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//生成一个随机的临时的queue
String queueName = channel.queueDeclare().getQueue();
//一个交换机同时绑定3个queue,接收其它消息类型更换绑定即可
//同时开启一个新的接收者即可实现分开按类型接收
channel.queueBind(queueName, EXCHANGE_NAME, "info");
channel.queueBind(queueName, EXCHANGE_NAME, "warning");
channel.queueBind(queueName, EXCHANGE_NAME, "error");
System.out.println("开始接收消息");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("收到消息:" + message);
}
};
channel.basicConsume(queueName, true, consumer);
}
}
Topic Exchange—主题类型交换机
将路由键和某模式进行匹配。此时队列需要绑定某一个模式上。符号#匹配0个或多个单词,符号 *匹配一个单词。
发送
/**
* EmitLogTopic 类用于演示如何向 RabbitMQ 的主题交换器发送消息。
* 主函数中创建了一个连接到 RabbitMQ 服务器的连接,并声明了一个主题交换器。
* 然后,向该交换器发布了一系列消息,每个消息都绑定到不同的路由键上。
*/
public class EmitLogTopic {
// 定义要声明的交换器的名称
private static final String EXCHANGE_NAME = "topic_logs";
/**
* 主函数:创建连接和通道,声明交换器,发布消息到交换器。
* @param args 命令行参数(未使用)
* @throws IOException 如果发生 I/O 错误
* @throws TimeoutException 如果连接超时
*/
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂并设置主机地址为本地主机
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
// 建立到 RabbitMQ 服务器的新连接
Connection connection = factory.newConnection();
// 创建一个新的通道
Channel channel = connection.createChannel();
// 声明一个主题类型的交换器
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
// 准备发送的消息内容
String message = "Animal World";
// 定义一系列路由键,以演示不同的绑定
String[] routingKeys = new String[9];
routingKeys[0] = "quick.orange.rabbit";
routingKeys[1] = "lazy.orange.elephant";
routingKeys[2] = "quick.orange.fox";
routingKeys[3] = "lazy.brown.fox";
routingKeys[4] = "lazy.pink.rabbit";
routingKeys[5] = "quick.brown.fox";
routingKeys[6] = "orange";
routingKeys[7] = "quick.orange.male.rabbit";
routingKeys[8] = "lazy.orange.male.rabbit";
// 循环发布消息到交换器,每个消息绑定到不同的路由键
for (int i = 0; i < routingKeys.length; i++) {
channel.basicPublish(EXCHANGE_NAME, routingKeys[i], null, message.getBytes("UTF-8"));
System.out.println("发送了:" + message + " routingKey:" + routingKeys[i]);
}
// 关闭通道和连接
channel.close();
connection.close();
}
}
接收
/**
* 这个类用于演示如何从一个RabbitMQ的主题交换器中接收消息。
* 它会连接到本地的RabbitMQ服务器,声明一个主题交换器,创建一个临时队列,
* 并将该队列绑定到一个带有通配符的主题上,从而可以接收匹配该主题的消息。
*/
public class ReceiveLogsTopic1 {
private static final String EXCHANGE_NAME = "topic_logs"; // 定义交换器的名称
/**
* 主函数:创建连接、通道,声明交换器、队列,绑定队列和交换器,以及消费消息。
* @param args 命令行参数(未使用)
* @throws IOException 如果发生I/O错误
* @throws TimeoutException 如果连接超时
*/
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂并设置连接RabbitMQ服务器的参数
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("password");
// 建立与RabbitMQ服务器的连接
Connection connection = factory.newConnection();
// 创建一个新的通道
Channel channel = connection.createChannel();
// 声明一个主题交换器
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
// 生成一个随机的临时的queue
String queueName = channel.queueDeclare().getQueue();
// 使用通配符绑定队列到交换器,以接收特定模式的消息
// * 匹配一个字符,# 匹配多个字符
String routingKey = "*.orange.*";
channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
System.out.println("开始接收消息");
// 定义消息消费者并启动消费过程
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// 消费消息并打印出来
String message = new String(body, "UTF-8");
System.out.println("收到消息:" + message + " routingKey: " + envelope.getRoutingKey());
}
};
channel.basicConsume(queueName, true, consumer);
}
}
Headers Exchanges
这种不常用,可以选择性忽略
整合spring
pom添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
生产者
配置
/**
* 描述: rabbitmq配置类
*/
@Configuration // 标识为配置类
public class TopicRabbitConfig {
/**
* 创建并配置一个名为 "queue1" 的队列。
*
* @return Queue 返回一个RabbitMQ队列对象。
*/
@Bean
public Queue queue1() {
return new Queue("queue1");
}
/**
* 创建并配置一个名为 "queue2" 的队列。
*
* @return Queue 返回一个RabbitMQ队列对象。
*/
@Bean
public Queue queue2() {
return new Queue("queue2");
}
/**
* 创建并配置一个名为 "bootExchange" 的主题交换器。
*
* @return TopicExchange 返回一个RabbitMQ主题交换器对象。
*/
@Bean
TopicExchange exchange() {
return new TopicExchange("bootExchange");
}
/**
* 将队列 "queue1" 绑定到 "bootExchange" 交换器上,绑定键为 "dog.red"。
*
* @param queue1 队列对象。
* @param exchange 交换器对象。
* @return Binding 返回一个绑定对象。
*/
@Bean
Binding bingdingExchangeMessage1(Queue queue1, TopicExchange exchange) {
return BindingBuilder.bind(queue1).to(exchange).with("dog.red");
}
/**
* 将队列 "queue2" 绑定到 "bootExchange" 交换器上,绑定键为 "dog.#"。
* 这样的绑定可以匹配以 "dog" 开头的所有路由键。
*
* @param queue2 队列对象。
* @param exchange 交换器对象。
* @return Binding 返回一个绑定对象。
*/
@Bean
Binding bingdingExchangeMessage2(Queue queue2, TopicExchange exchange) {
return BindingBuilder.bind(queue2).to(exchange).with("dog.#");
}
}
发送信息
/**
* 描述: 发送消息
*/
@Component
public class MsgSender {
@Autowired
private AmqpTemplate rabbitmqTemplate;
/**
* 此方法用于发送一条消息到RabbitMQ,消息内容与路由键相关联。
* @param message 消息内容,描述为"This is message 1, routing key is dog.red"
* @see #rabbitmqTemplate RabbitMQTemplate实例,用于实际的消息发送操作
*/
public void send1() {
String message = "This is message 1, routing key is dog.red";
System.out.println("发送了:"+message);
// 使用RabbitMQTemplate,通过指定的交换机"bootExchange"和路由键"dog.red"发送消息
this.rabbitmqTemplate.convertAndSend("bootExchange", "dog.red", message);
}
public void send2() {
String message = "This is message 2, routing key is dog.black";
System.out.println("发送了:"+message);
this.rabbitmqTemplate.convertAndSend("bootExchange", "dog.black", message);
}
}
消费者
/**
* 描述: 消费者1
*/
@Component
@RabbitListener(queues = "queue1")
public class Receiver1 {
@RabbitHandler
public void process(String message) {
System.out.println("Receiver1: " + message);
}
}
/**
* 描述: 消费者2
*/
@Component
@RabbitListener(queues = "queue2")
public class Receiver2 {
@RabbitHandler
public void process(String message) {
System.out.println("Receiver2: " + message);
}
}