ルーティングルーティングモデルでは、routingKeyに基づいて対応するメッセージキューにメッセージを選択的に送信できることに気付きましたが、このモデルは十分な柔軟性がありません。たとえば、最初は3種類のログ、警告、情報しかありません。 、エラー、およびしかし、後で胎児タイプのログを追加する必要がある場合は、元のコードを変更する必要があります。これは、開始と終了の原則に準拠していません。トピックモデルを使用すると、この点をより適切に満たすことができ、拡張用のワイルドカードをサポートします。
それでも、公式文書で詳細な説明を見ることができます。使用*
番号は1つの単語#
を置き換えることができ、使用番号は0以上の単語を置き換えることができます。したがって、すべてのタイプのroutingKeyに適応したい場合は、その#
番号をroutingKeyとして使用してください。さらに、rabbitmqは、routingKey.
として複数の単語を接続するために使用することを公式に推奨しています。
古いルール、今回はトピックタイプスイッチを使用する必要があります。既存のルールを使用することも、自分で新しいルールを宣言することもできます。
- プロデューサー
public class Provider {
public void send() throws IOException, TimeoutException {
Connection connection = null;
Channel channel = null;
try {
connection = ConnectionUtils.getConnection();
// 获取连接通道
channel = connection.createChannel();
// 定义通道对应的交换机 参数一:交换机名称 参数二:类型 direct
channel.exchangeDeclare("amqp.topic","topic");
String routingKey = "log.info";
// 发送消息
channel.basicPublish("amqp.topic",routingKey,null,("topic message,routingKey为:" + routingKey + "," + System.currentTimeMillis()).getBytes());
}finally {
if (channel !=null && channel.isOpen()) {
channel.close();
}
if (connection != null && connection.isOpen()) {
connection.close();
}
}
}
public static void main(String[] args) throws IOException, TimeoutException {
Provider provider = new Provider();
provider.send();
}
}
- 消費者
消費者1
public class Consumer01 {
public void consume() throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
// 获取连接通道
final Channel channel = connection.createChannel();
// 绑定交换机
channel.exchangeDeclare("amqp.topic","topic");
//创建临时队列
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queueName,"amqp.topic","#");
// 每次只能消费一个消息
channel.basicQos(1);
// 消费消息
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费消息:" + new String(body));
//参数一:确认队列中的那个消息 参数二:是否开启多个消息同时确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
public static void main(String[] args) throws IOException, TimeoutException {
Consumer01 consumer = new Consumer01();
consumer.consume();
}
}
コンシューマー1では、#
さまざまなタイプのメッセージを受信するためのroutingKeyとして番号を使用します。
消費者2:
public class Consumer02 {
public void consume() throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
// 获取连接通道
final Channel channel = connection.createChannel();
// 绑定交换机
channel.exchangeDeclare("amqp.topic","topic");
//创建临时队列
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机和队列
channel.queueBind(queueName,"amqp.topic","*.error");
// 每次只能消费一个消息
channel.basicQos(1);
// 消费消息
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费消息:" + new String(body));
//参数一:确认队列中的那个消息 参数二:是否开启多个消息同时确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
public static void main(String[] args) throws IOException, TimeoutException {
Consumer02 consumer = new Consumer02();
consumer.consume();
}
}
コンシューマIIは、*
単語の代わりに数字を使用して.error
、末尾がルーティングキータイプのメッセージを受信します。
コンシューマー1とコンシューマー2をテスト開始し、プロデューサーを実行して、log.infoのroutingKeyを使用してメッセージを送信します。
コンシューマー1:
コンシューマー2:
すぐに、file.errorのroutingKeyを使用して別のメッセージを送信します。
この時点で、コンシューマー1:
コンシューマー2: