上一篇文章使用的是直連交換機,她還是不夠靈活變通,不能基於多標準進行路由設定。
主題換件機 exchange topic 可以幫助我們解決這個問題。
主題交流
發送到 主題交換機的消息不能具有任意的 routingKey ,他必須由點分隔的單詞列表,單詞可以是任何內容,但通過他們指定與消息相關的一些功能。路由祕鑰中可以包含任意數量的單詞,最多可達到255個字節。
綁定祕鑰也必須採取相同的形式,主題交換機背後的邏輯類似於 直連交換機。使用特定路由祕鑰發送的消息將被傳遞到與匹配綁定祕鑰綁定的所有隊列。
綁定鍵有兩個重要的特殊情況:* 星號,可以代替一個單詞,# 井號可以替換零個或多個單詞。
舉個例子!
在這例子中,我們將發送所有描述動物的消息。消息將與包含三個單詞(兩個點)的路由鍵一起發送,路由鍵中的第一個單詞將描述速度,第二個將描述顏色,第三個將描述物種:speed.color.species
我們創建了三個綁定:Q1綁定了 綁定祕鑰爲:.orange. ,Q2綁定了 綁定祕鑰爲:..rabbit 和 lazy.#
這些綁定可以概括爲:
Q1對所有橙色的動物感興趣
Q2對兔子的一切感興趣,以及懶惰動物的一切。
路由祕鑰設置爲“ quick.orange.rabbit ”的消息將傳遞到兩個隊列去。
路由祕鑰設置爲“ lazy.orange.elephant ”的消息也將會傳遞到兩個隊列去。
路由祕鑰設置爲“ quick.orange.fox ”的消息會傳遞到第一個Q1的隊列去。
路由祕鑰設置爲“ lazy.brown.fox ”的消息會傳到第二個Q2的隊列去。
路由祕鑰設置爲“ lazy.pink.rabbit ”的消息也會傳遞到第二個Q2的隊列去,即使它匹配了兩個綁定。
路由祕鑰設置爲“ quick.brown.fox ”的消息不匹配任何綁定,它將被丟棄。
另一個路由祕鑰設置爲“ quick.orange.maie.rabbit ”的消息,也將會被丟棄。
路由祕鑰設置爲“ lazy.orange.maie.rabbit”,及時他有4個單詞,也會匹配上Q2對列的綁定。
貼代碼
生產者代碼
public class TopicsSend {
final static String EXCHANGE_NAME = "Topics_test";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//聲明交換機 指定direct直連類型
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
String message1 = "Exchange type topic, test error.test.info";
String severity = "error.test.info";
//發佈到交換機
channel.basicPublish(EXCHANGE_NAME, severity, null, message1.getBytes());
System.out.println("綁定祕鑰:"+severity+", 消息:"+message1);
String message2 = "Exchange type topic, test info.test.action";
String severity2 = "info.test.action";
//發佈到交換機
channel.basicPublish(EXCHANGE_NAME, severity2, null, message2.getBytes());
System.out.println("綁定祕鑰:"+severity2+", 消息:"+message2);
String message3 = "Exchange type topic, test warning.info.action";
String severity3 = "warning.info.action";
//發佈到交換機
channel.basicPublish(EXCHANGE_NAME, severity3, null, message3.getBytes());
System.out.println("綁定祕鑰:"+severity3+", 消息:"+message3);
// 關閉通道和連接
channel.close();
conn.close();
}
}
消費者 *.test.*代碼
public class TopicsReceiver {
final static String EXCHANGE_NAME = "Topics_test";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//聲明交換機 指定direct直連類型
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
//獲取臨時隊列名稱
String queneName = channel.queueDeclare().getQueue();
//綁定隊列 綁定祕鑰 *.test.*
channel.queueBind(queneName, EXCHANGE_NAME, "*.test.*");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("接受類型:*.test.* , 路由祕鑰:"+delivery.getEnvelope().getRoutingKey()+",接受消息: '" + message + "'");
};
channel.basicConsume(queneName, true, deliverCallback, consumerTag -> {});
}
}
消費者2 error.# 代碼
public class RoutingReceiver2 {
final static String EXCHANG_NAME = "Topics_test";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
//聲明交換機 指定direct直連類型
channel.exchangeDeclare(EXCHANG_NAME, "topic");
//獲取臨時隊列名稱
String queneName = channel.queueDeclare().getQueue();
//綁定隊列 error.#
channel.queueBind(queneName, EXCHANG_NAME, "error.#");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("接受類型:error.# , 路由祕鑰:"+delivery.getEnvelope().getRoutingKey()+",接受消息: '" + message + "'");
};
channel.basicConsume(queneName, true, deliverCallback, consumerTag -> {});
}
}