基本概念
- RabbitMQ也可以叫做消息队列,用来作为中间件
- 优点
- 解耦
- 异步
- 削峰
- 和其他中间件相比,不容易丢失数据,高可用,性能相比Kafka来说中规中举,但是数据的完整性比Kafka强,比较适合中小项目使用。
- 优点
运行RabbitMQ
- 初始的队列如下
入门案例
- 导入依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
简单队列模式
就突出两个字,简单,生产者往队列里塞消息,消费者往队列里面取消息,其他啥的也不管。
例子:
- 消息生产者的定义
- 1.定义队列的名称
- 2.创建连接工厂的对象(ConnectionFactory)
- 3.根据连接工厂的对象获取连接
- 4.根据获取到的连接创建信道
- 5.通过信道绑定队列
- 6.定义要发送的消息
- 7.通过信道发送消息
- 8.关闭连接和信道
package send;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.nio.charset.StandardCharsets;
public class Send {
//1.声明队列名称
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (
//3.根据连接工厂获取连接
Connection connection = factory.newConnection();
//4.根据连接创建信道
Channel channel = connection.createChannel()) {
/*
5.通过信道绑定队列
@Param1 队列的名称
@Param2 持久化
@Param3 排他队列(仅对首次声明他的链接可见,如果链接关掉了,排他队列的值也会被删掉)
@Param4 自动删除
@Param5 自己携带的参数
*/
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//6
String message = "Hello World!";
/*7.通过信道发送消息到队列
* @Param1 交换机
* @Param2 队列名称
* @Param3 自己附带的参数
* @Param4 消息的实体
*/
channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + message + "'");
}
}
}
启动消息生产者。
这里可以看到我们的队列中多了一个hello队列,且里面有一条消息没有被消费。
- 消息消费者的定义
- 1.定义队列的名称
- 2.创建连接工厂的对象(ConnectionFactory)
- 3.根据连接工厂的对象获取连接
- 4.根据获取到的连接创建信道
- 5.通过信道绑定队列
- 6.监听消息队列 回调消费消息
package accept;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import java.nio.charset.StandardCharsets;
public class Recv {
//1.声明队列名称
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听消息队列
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
}
}
启动消息消费者。
我们发现hello队列中的消息被消费掉了。这就是简单队列。优点就是简单,但是缺点就很多啦。
生产者只管生产,消费者只管消费,没有考虑到消费者的消费能力问题。
大家想一下,如果生产者一天生产500条消息,但是我们的消费者一天只能消费100条消息,这样下去是不是每天都要积压四百条数据,是不是会导致一些消息永远也不会被消费,而且队列长度越来越长,占用的内存越来越大,最后就是宕机的结果。
那怎么解决这种问题?产力过剩我们增加消费者就好了,比如我们在增加4个消费者,那就是五个消费者。五个消费者就能消费完这500条消息。增加消费者就变成了工作队列。
工作队列
工作队列有两种模式,轮询和公平。
轮询就是字面上的意思,就是当有多个消费者存在时,每人消费一条的来,我消费了到你,你消费了到我。
- 实现轮询
给定两个消费者(减慢消费速度),一个生产者
消费者1
package work.accept;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import java.nio.charset.StandardCharsets;
/**
* 工作队列--轮询--消费者
*/
public class Recv {
//1.声明队列名称
private final static String QUEUE_NAME = "work_poll";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
//模拟消费消息慢的场景
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
//手动确认消息,即使我收到了多条消息,我也一条一条的去手动确认
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
};
//6.监听消息队列
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });
}
}
消费者2
package work.accept;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import java.nio.charset.StandardCharsets;
/**
* 工作队列- 轮询---消费者1
*/
public class Recv1 {
//1.声明队列名称
private final static String QUEUE_NAME = "work_poll";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
//模拟消费消息慢的场景
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
//手动确认消息,即使我收到了多条消息,我也一条一条的去手动确认
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
};
//6.监听消息队列
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });
}
}
生产者
package work.send;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.nio.charset.StandardCharsets;
/**
* 工作队列 ---轮询--生产者
*/
public class Send {
//1.声明队列名称
private final static String QUEUE_NAME = "work_poll";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (
//3.根据连接工厂获取连接
Connection connection = factory.newConnection();
//4.根据连接创建信道
Channel channel = connection.createChannel()) {
/*
5.通过信道绑定队列
@Param1 队列的名称
@Param2 持久化
@Param3 排他队列(仅对首次声明他的链接可见,如果链接关掉了,排他队列的值也会被删掉)
@Param4 自动删除
@Param5 自己携带的参数
*/
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//生产者生产20条消息
for (int i = 0; i < 20; i++) {
//6
String message = "Hello World!"+i;
/*7.通过信道发送消息到队列
* @Param1 交换机
* @Param2 队列名称
* @Param3 自己附带的参数
* @Param4 消息的实体
*/
channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + message + "'"+i);
}
}
}
}
依次运行消费者1,消费者2,生产者,我们可以通过控制台观察两个消费者的消费情况,如下,
这就是工作队列中的轮询模式,主要解决生产者的生产能力远远大于消费者的消费能力时,防止消息积累的问题。
- 公平模式(工作队列)
- 轮询模式的效率不高,当两个消费者消费能力差距过大时,先消费完的得等着,造成一种资源的浪费,消费时间过长等问题。
- 所以公平模式就是说,如果有先消费完了的消费者,则先消费完的消费者去帮没有消费完的消费者消费它的任务,尽你所能的去消费,所以这个公平和我们生活中的公平是不一样的,这里的公平模式是能力越强,责任越大。
- 公平模式的设置非常简单,就是不让他们提前去分配消息,限制消费者处理完当前的消息再去消费消息,这样速度快的就会多消费,速度慢的就会少消费。整体上就不会出现等和资源的浪费,减短了整体的消费时间。
- 怎么设置公平模式?在消费者中添加一下代码即可。
//限制消费者每次只能接收一条消息,处理完才能接受下一条
int prefetchCount=1;
channel.basicQos(prefetchCount);
ava
其余的代码和轮询案例中的一样,只需要在消费者中加入这个限设置即可从轮询模式转变为公平模式。
发布-订阅队列
当我们的需求越来越复杂,前面两种模式就不能满足我们的需求了,通过案例我们可以看到,前面的两种模式,消费者是不可能拿到重复的数据的。前面两种模式是如果消息已经被消费者消费了,那么其他消费者就去消费其他的消息,是不可能拿到和其他消费者相同的一个消息的,
那现在如果我想要让所有的消费者都收到我发出去的同一条信息,那我们应该怎么实现呢,没错,就是现在要说的发布-订阅队列模式。
怎么实现?借助交换机,生产者生产的消息,会先发送到交换机中,在由交换机将生产者生产的数据分发给队列,然后监听每个队列的消费者就会获取到交换机转发到队列中的数据,这样所有的队列拿到的数据都是由交换机转发的相同数据。
大致如图
代码实现:
消费者实现步骤:
- 定义交换机名称(使用广播类型)
- 创建连接工厂
- 设置主机地址
- 通过连接工厂获取连接
- 获取连接之后开启信道(channel)
- 绑定交换机(channel.exchangeDeclare())
- 查询交换机中队列的名称(channel.queueDeclare().getQueue())
- 将交换机和队列进行绑定(chanel.queueBind())
- 监听队列
代码如下
package exchange.accept;
import com.rabbitmq.client.*;
import java.nio.charset.StandardCharsets;
/**
* 发布/订阅--消费者
*/
public class Recv1 {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_fanout";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
//6.获取交换机生成的队列名称(排他队列)
String byNameQueue = channel.queueDeclare().getQueue();
//7. 将队列和交换机进行绑定
channel.queueBind(byNameQueue,EXCHANGE_NAME,"");
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听通过交换机得到的消息队列
channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
}
}
相同的代码再次创建一个消费者
发布/订阅生产者步骤:
- 定义交换机名称(使用广播类型)
- 创建连接工厂
- 设置主机地址
- 通过连接工厂获取连接
- 获取连接之后开启信道(channel)
- 绑定交换机(channel.exchangeDeclare())
- 上传消息到交换机
发布/订阅 生产者代码如下:
package exchange.send;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.nio.charset.StandardCharsets;
/**
* 订阅、发布 ---生产者
*/
public class Send {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_fanout";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (
//3.根据连接工厂获取连接
Connection connection = factory.newConnection();
//4.根据连接创建信道
Channel channel = connection.createChannel()) {
//5.绑定带交换机 //Fanout交换机的类型(广播模式)
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
String message = "Hello World!";
channel.basicPublish( EXCHANGE_NAME, "",null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + message + "'");
}
}
}
先运行两个消费者,让他们监听队列,然后在运行生产者,不出意外两个消费者会收到相同的消息。
路由队列
刚说完发布/订阅队列,这就又来问题了,发布/订阅队列是通过交换机向不同的队列推送数据。那我现在如果说,我不想要所有人都可以接受到我的消息,我只想给部分消费者发送消息,怎么实现?
使用路由队列,在绑定交换机和队列的时候,通过路由key(routin key)的参数设置交换机转发的路由,使得交换机可以根据路由转发消息(交换机是直连模式)。
重点看代码,代码中有相应的注释:
路由队列:生产者
package direct.send;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.nio.charset.StandardCharsets;
/**
* 路由队列 ---生产者
*/
public class Send {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_direct";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (
//3.根据连接工厂获取连接
Connection connection = factory.newConnection();
//4.根据连接创建信道
Channel channel = connection.createChannel()) {
//5.绑定带交换机 //Fanout交换机的类型(广播模式)
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
String infoMessage = "普通信息!";
String errorMessage = "错误信息!";
String warningMessage = "警告信息!";
//路由信息
String infoRoutingKey = "info!";
String errorRoutingKey = "error!";
String warningRoutingKey = "warning!";
//发送信息,并且携带路由的key
channel.basicPublish( EXCHANGE_NAME, infoRoutingKey,null, infoMessage.getBytes(StandardCharsets.UTF_8));
channel.basicPublish( EXCHANGE_NAME, errorRoutingKey,null, errorMessage.getBytes(StandardCharsets.UTF_8));
channel.basicPublish( EXCHANGE_NAME, warningRoutingKey,null, warningMessage.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + infoMessage + "'");
System.out.println(" [x] Sent '" + errorMessage + "'");
System.out.println(" [x] Sent '" + warningMessage + "'");
}
}
}
只能访问错误数据的消费者
package direct.accept;
import com.rabbitmq.client.*;
import java.nio.charset.StandardCharsets;
/**
* 路由队列--消费者
*/
public class Recv {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_direct";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//6.获取交换机生成的队列名称(排他队列)
String byNameQueue = channel.queueDeclare().getQueue();
//7. 将队列和交换机进行绑定同时绑定路由
String errorRoutingKey = "error!";
channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey); //该路由表示当前消费者只能接收错误的信息
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听通过交换机得到的消息队列
channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
}
}
三个路径都可以访问的消费者
package direct.accept;
import com.rabbitmq.client.*;
import java.nio.charset.StandardCharsets;
/**
* 路由队列--消费者
*/
public class Recv1 {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_direct";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//6.获取交换机生成的队列名称(排他队列)
String byNameQueue = channel.queueDeclare().getQueue();
//7. 将队列和交换机进行绑定同时绑定路由
String infoRoutingKey = "info!";
String errorRoutingKey = "error!";
String warningRoutingKey = "warning!";
channel.queueBind(byNameQueue,EXCHANGE_NAME,infoRoutingKey); //表示可以当前的消费者可以获取这三个路由下的内容。
channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey);
channel.queueBind(byNameQueue,EXCHANGE_NAME,warningRoutingKey);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听通过交换机得到的消息队列
channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
}
}
运行生产者,可以看见提交了三个信息,同时给这三个信息设置了路由:
很清楚的看到,两个消费者一个获取了三个信息,一个只获得了错误信息,这就是路由队列。
主题队列
路由队列虽然定制性强,但是当我们的项目越来越庞大的时候,相应的路由key就越来越多,难以维护和管理。
所以主题队列就是为了解决改善这一问题,它是在路由队列的基础上,在绑定路由key的时候,将写死的路由变成了正则表达式。前提交换机要更改为topic模式,且生产数据时要传递完整的路由名称,生产数据时不可以使用正则表达式(*表示可以匹配一个路由key,#表示可以匹配多个路由key)。
消费者:
package topic.accept;
import com.rabbitmq.client.*;
import java.nio.charset.StandardCharsets;
/**
* 主题队列-消费者
*/
public class Recv {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_topic";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
//6.获取交换机生成的队列名称(排他队列)
String byNameQueue = channel.queueDeclare().getQueue();
//7. 将队列和交换机进行绑定同时绑定路由
String errorRoutingKey = "#.message.#";
channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey); //该路由表示当前消费者只能接收错误的信息
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听通过交换机得到的消息队列
channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
}
}
消费者2
package topic.accept;
import com.rabbitmq.client.*;
import java.nio.charset.StandardCharsets;
/**
* 主题队列--消费者
*/
public class Recv1 {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_topic";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置主机地址
factory.setHost("localhost");
//3.获取连接
Connection connection = factory.newConnection();
//4.开启信道
Channel channel = connection.createChannel();
//5.绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
//6.获取交换机生成的队列名称(排他队列)
String byNameQueue = channel.queueDeclare().getQueue();
//7. 将队列和交换机进行绑定同时绑定路由
String RoutingKey = "*.rabbit.*!";
channel.queueBind(byNameQueue,EXCHANGE_NAME,RoutingKey); //表示可以当前的消费者可以获取这三个路由下的内容。
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//监听消息队列的回调函数
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received '" + message + "'");
};
//6.监听通过交换机得到的消息队列
channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
}
}
生产者:
package topic.send;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.nio.charset.StandardCharsets;
/**
* 主题队列 ---生产者
*/
public class Send {
//1.声明交换机名称
private final static String EXCHANGE_NAME = "exchange_topic";
public static void main(String[] argv) throws Exception {
//2.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (
//3.根据连接工厂获取连接
Connection connection = factory.newConnection();
//4.根据连接创建信道
Channel channel = connection.createChannel()) {
//5.绑定带交换机 //Fanout交换机的类型(广播模式)
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
String infoMessage = "普通信息!";
String errorMessage = "错误信息!";
String warningMessage = "警告信息!";
//路由信息
String infoRoutingKey = "info.message.orange";
String errorRoutingKey = "error.rabbit.lazy";
String warningRoutingKey = "warning.warning.message";
//发送信息,并且携带路由的key
channel.basicPublish( EXCHANGE_NAME, infoRoutingKey,null, infoMessage.getBytes(StandardCharsets.UTF_8));
channel.basicPublish( EXCHANGE_NAME, errorRoutingKey,null, errorMessage.getBytes(StandardCharsets.UTF_8));
channel.basicPublish( EXCHANGE_NAME, warningRoutingKey,null, warningMessage.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent '" + infoMessage + "'");
System.out.println(" [x] Sent '" + errorMessage + "'");
System.out.println(" [x] Sent '" + warningMessage + "'");
}
}
}
运行结果:
可以看到能够根据正则表达式去匹配相应的路由key,这个就是主题模式。