[TOC]
# 1. 多重綁定
Direct 交換機可以選擇將哪些消息發送到哪些隊列上,不將哪些消息發送到哪些隊列上。

上圖中,我們可以看到 X 綁定了兩個隊列,交換機類型是 direct。隊列 Q1 綁定鍵為 orange,隊列 Q2 綁定鍵有兩個:一個綁定鍵為 black,另一個綁定鍵為 green。
<br/>
在這種綁定情況下,生產者發布消息到 exchange 上,綁定鍵為 orange 的消息會被發布到隊列 Q1。綁定鍵為 black、green 的消息會被發布到隊列 Q2,其他沒有被綁定的消息將被丟棄。
<br/>
:-: 
多重綁定
當 exchange 類型是 direct,但是它綁定的多個隊列的 key 都相同,在這種情況下雖然 exchange 類型是 direct,但是它表現的就和 fanout 交換機有點類似了,就跟廣播差不多。
<br/>
# 2. Direct交換機演示
演示下圖的 Direct 交換機。

步驟如下:
**1. 生產者**
```java
public class EmitLogDirect {
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] argv) throws Exception {
try (Channel channel = RabbitMQUtils.getChannel()) {
//聲明exchange類型
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
//創建多個 bindingKey
Map<String, String> bindingKeyMap = new HashMap<>();
bindingKeyMap.put("info", "info信息");
bindingKeyMap.put("warning", "warning信息");
bindingKeyMap.put("error", "error信息");
bindingKeyMap.put("debug", "debug信息");
for (Map.Entry<String, String> bindingKeyEntry : bindingKeyMap.entrySet()) {
String bindingKey = bindingKeyEntry.getKey();
String message = bindingKeyEntry.getValue();
/*
* 發送消息。
* basicPublish(String var1, String var2, BasicProperties var3, byte[] var4)
* var1: 交換機名稱
* var2: bindingKey名稱
* var3: 其他參數
* var4: 發送的消息
*/
channel.basicPublish(EXCHANGE_NAME, bindingKey, null, message.getBytes("UTF-8"));
System.out.println(EmitLogDirect.class.getSimpleName() + "[生產者發出消息]: " + message);
}
}
}
}
```
**2. 兩個消費者**
(1)*`ReceiveLogsDirect01`*
```java
public class ReceiveLogsDirect01 {
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] argv) throws Exception {
Channel channel = RabbitMQUtils.getChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
String queueName = "queue.error";
//聲明一個隊列
channel.queueDeclare(queueName, false, false, false, null);
//隊列與交換機綁定,綁定的key=error
channel.queueBind(queueName, EXCHANGE_NAME, "error");
System.out.println(ReceiveLogsDirect01.class.getSimpleName() + "[等待接收消息...]");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
message = "bindKey=" + delivery.getEnvelope().getRoutingKey() + ", msg=" + message;
System.out.println(ReceiveLogsDirect01.class.getSimpleName() + "[接收到的消息]: " + message);
};
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
});
}
}
```
(2)*`ReceiveLogsDirect02`*
```java
public class ReceiveLogsDirect02 {
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] argv) throws Exception {
Channel channel = RabbitMQUtils.getChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
String queueName = "queue.console";
channel.queueDeclare(queueName, false, false, false, null);
//注意:這里綁定了兩個key
channel.queueBind(queueName, EXCHANGE_NAME, "info");
channel.queueBind(queueName, EXCHANGE_NAME, "warning");
System.out.println(ReceiveLogsDirect02.class.getSimpleName() + "[等待接收消息...]");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
message = "bindKey=" + delivery.getEnvelope().getRoutingKey() + ", msg=" + message;
System.out.println(ReceiveLogsDirect02.class.getSimpleName() + "[接收到的消息]: " + message);
};
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
});
}
}
```
**3. 測試**
先啟動兩個消費者,再啟動生產者并生產4條消息,控制臺輸出如下。
```
-----------EmitLogDirect生產者生產了4條消息-----------
EmitLogDirect[生產者發出消息]: debug信息
EmitLogDirect[生產者發出消息]: warning信息
EmitLogDirect[生產者發出消息]: error信息
EmitLogDirect[生產者發出消息]: info信息
-----------ReceiveLogsDirect01消費者收到了error消息-----------
ReceiveLogsDirect01[接收到的消息]: bindKey=error, msg=error信息
-----------ReceiveLogsDirect02消費者收到warning與info共兩條消息-----------
ReceiveLogsDirect02[接收到的消息]: bindKey=warning, msg=warning信息
ReceiveLogsDirect02[接收到的消息]: bindKey=info, msg=info信息
```
由于`debug`消息沒有與任何隊列綁定,所以被丟棄了。
****
案例代碼:https://gitee.com/flymini/codes01/tree/master/rabbitmq_/com-learn-rabbitmq01
- 消息隊列
- 什么是MQ
- MQ的作用
- MQ的分類
- MQ的選擇
- RabbitMQ
- RabbitMQ是什么
- 四大核心概念
- 工作原理
- 環境搭建
- windows系統下的搭建
- centos7系統下的搭建
- 常用命令
- 服務相關命令
- 管理用戶命令
- 管理隊列命令
- 第一個RabbitMQ程序
- 工作隊列
- 輪詢分發消息
- 消息應答
- 持久化
- 發布確認
- 發布確認原理
- 發布確認策略
- 交換機概念
- 交換機類型
- 無名交換機
- Fanout交換機
- Direct交換機
- Topic交換機
- 死信隊列
- 死信概念
- 死信來源
- 死信實戰
- 延遲隊列
- 什么是延遲隊列
- TTL設置方式
- 隊列TTL延遲隊列
- 消息TTL延遲隊列
- 插件打造延遲隊列
- 延遲隊列總結
- 發布確認高級
- 代碼實現
- 回退消息
- 備份交換機
- 冪等性
- 冪等性概念
- 消息重復消費
- 消費端冪等性保障
- 優先級隊列
- 使用場景
- 設置優先級
- 惰性隊列
- 什么是惰性隊列
- 隊列的兩種模式
- 聲明惰性隊列
- RabbitMQ集群
- 為什么要搭建集群
- 集群搭建步驟
- 集群工作方式
- 脫離集群
- 鏡像隊列
- 高可用負載均衡