(一)routing路由模式
在前面一篇博客中講到了exchange的類型,其中direct類型的exchange就是用於routing路由模式。direct類型的交換機是指:交換機和隊列綁定時會設置路由鍵(routingkey),當消息從生產者發送給交換機時也會發送一個路由鍵。只有當這兩個路由鍵相同時,交換機纔會把消息發送給隊列。
如上圖所示,當生產者發送消息的路由鍵爲error時,兩個隊列均可以收到消息;當生產者發送消息的路由鍵爲info或warning時,只有第二個隊列可收到消息。
(二)路由模式實踐
2.1 工具類
public class ConnectionUtil {
public static Connection getConnection() throws IOException, TimeoutException {
//定義一個連接工廠
ConnectionFactory factory=new ConnectionFactory();
//設置服務地址
factory.setHost("127.0.0.1");
//設置AMQP端口
factory.setPort(5672);
//設置VHOSTS
factory.setVirtualHost("/vhosts_sdxb");
//設置用戶名
factory.setUsername("user_sdxb");
factory.setPassword("123456");
return factory.newConnection();
}
}
2.2 生產者
與前面幾種模式不同的地方已經通過註解標出,其中交換機類型選擇成direct,並且按需要設置路由鍵
public class Sent {
private static final String EXCHANGENAME="routing_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//交換機類型選擇direct
channel.exchangeDeclare(EXCHANGENAME,"direct");
String msg="hello world";
//設置路由鍵(routingkey)
String routingkey="error";
channel.basicPublish(EXCHANGENAME,routingkey,null,msg.getBytes());
channel.close();
connection.close();
}
}
2.3 消費者一
public class Receive1 {
private static final String QUEUENAME="routing_queue1";
private static final String EXCHANGENAME="routing_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(QUEUENAME, false, false, false, null);
//在隊列綁定時設置路由鍵
channel.queueBind(QUEUENAME, EXCHANGENAME, "error");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "utf-8");
System.out.println("receive:" + msg);
}
};
//監聽隊列
channel.basicConsume(QUEUENAME, true, consumer);
}
}
2.4 消費者二
public class Receive2 {
private static final String QUEUENAME="routing_queue2";
private static final String EXCHANGENAME="routing_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(QUEUENAME, false, false, false, null);
//在隊列綁定時設置多個路由鍵
channel.queueBind(QUEUENAME, EXCHANGENAME, "error");
channel.queueBind(QUEUENAME, EXCHANGENAME, "info");
channel.queueBind(QUEUENAME, EXCHANGENAME, "warning");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "utf-8");
System.out.println("receive:" + msg);
}
};
//監聽隊列
channel.basicConsume(QUEUENAME, true, consumer);
}
}
2.5運行結果
當路由鍵爲error時,兩個消費者均輸出消息。當路由鍵爲info或warning時,只有第二個消費者輸出消息。
(三)Topic主題模式
Topic主題模式和routing路由模式類似,只不過這裏的交換機使用的是topic類型,topic類型的交換機和direct的不同就在於topic可以匹配通配符。*代表匹配一個元素,#代表匹配一個或多個元素
以上圖爲例,Q1隊列的路由鍵爲*.orange.*,Q2隊列的路由鍵爲*.*.rabbit和lazy.#,當消息的路由鍵爲quick.orange.rabbit時,兩個隊列均能收到,當消息的路由鍵爲lazy.orange.male.rabbit時,只有Q2隊列能收到。
(四)主題模式實踐
4.1 生產者
//交換機類型選擇direct
channel.exchangeDeclare(EXCHANGENAME,"topic");
//設置路由鍵(routingkey)
String routingkey="lazy.brown.fox";
4.2 消費者一
channel.queueBind(QUEUENAME, EXCHANGENAME, "*.orange.*");
4.3 消費者二
channel.queueBind(QUEUENAME, EXCHANGENAME, "*.*.rabbit");
channel.queueBind(QUEUENAME, EXCHANGENAME, "lazy.#");