RabbiteMQ的Fanout模式其實和ActiveMQ的Topic模式比較類似,這裏我們就來看一下見到的小例子吧,首先我們看生成者,這裏生產者和RabbitMQ的基礎使用 —— Direct模式(一)、RabbitMQ的基礎使用 —— Direct模式(二)中的類似,其中最重要的就是需要將交換器的類型修改爲Fanout
,如下:
public class FanoutProducer {
//交換器名稱
public static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws Exception {
//創建連接,連接到RabbitMQ
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
//創建信道
Channel channel = connection.createChannel();
//創建交換器
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
//定義的業務日誌消息級別,即作爲路由鍵使用
String[] logLevels = {"error", "warn", "info"};
for (int i = 0; i < logLevels.length; i++) {
String logLevel = logLevels[i];
String msg = "Hello RabbitMQ";
//發佈消息,需要參數:交換器、路由鍵,其中以日誌消息級別爲路由鍵
channel.basicPublish(EXCHANGE_NAME, logLevel, null, msg.getBytes(Charset.forName("UTF-8")));
}
channel.close();
connection.close();
}
}
然後我們再來看看消費者端,這裏我們就用兩個消費者來進行測試,一個消費者綁定路由鍵error
,另一個消費者這綁定一個不存在的路由鍵other
,如下:
public class ErrorConsumer {
public static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws Exception {
//創建連接,連接到RabbitMQ,與發送端一樣
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
//創建信道
Channel channel = connection.createChannel();
//可不創建,由生產者進行創建
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
String queueName = "logError"; //聲明一個隊列名稱
String routingKey = "error"; //路由鍵名稱
//創建一個隊列
channel.queueDeclare(queueName, false, false, false, null);
//將隊列和交換器通過路由鍵進行綁定
channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
//聲明瞭一個消費者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
StringBuffer buffer = new StringBuffer();
buffer.append(Thread.currentThread().getName()).append(", ")
.append(envelope.getExchange()).append(", ")
.append(envelope.getRoutingKey()).append(", ")
.append(new String(body, "UTF-8"));
System.out.println(buffer.toString());
}
};
//消費者正式開始在指定隊列上消費消息
channel.basicConsume(queueName, true, consumer);
}
}
public class OtherConsumer {
public static final String EXCHANGE_NAME = "logs";
public static void main(String[] args) throws Exception {
//創建連接,連接到RabbitMQ,與發送端一樣
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
//創建信道
Channel channel = connection.createChannel();
//可不創建,由生產者進行創建
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
String queueName = "logOther"; //聲明一個隊列名稱
String routingKey = "other"; //路由鍵名稱
//創建一個隊列
channel.queueDeclare(queueName, false, false, false, null);
//將隊列和交換器通過路由鍵進行綁定
channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
//聲明瞭一個消費者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
StringBuffer buffer = new StringBuffer();
buffer.append(Thread.currentThread().getName()).append(", ")
.append(envelope.getExchange()).append(", ")
.append(envelope.getRoutingKey()).append(", ")
.append(new String(body, "UTF-8"));
System.out.println(buffer.toString());
}
};
//消費者正式開始在指定隊列上消費消息
channel.basicConsume(queueName, true, consumer);
}
}
按我們預期的效果來看,應該不管我們如何調整生產者和消費者的路由鍵,都對消息的接受沒有影響。下面我們進行測試,如下: