通过使用“*”和“#”,使来自不同源头的消息到达同一个队列,”.”将路由键分为了几个标识符,“*”匹配1个,“#”匹配一个或多个。例如日志处理:

假设有交换器log-exchange,

日志级别有error,info,warning,

应用模块有user,order,email,

服务器有 A、B、C、D

路由键的规则为 服务器+“.”+日志级别+“.”+应用模块名,如:A. info .email。

1、要关注A服务器发送的所有应用错误的消息,怎么做?

声明队列名称为“a-app-error-queue”并绑定到交换器上:channel. queueBind (‘a-app-error-queue’,’logs-change’,’A.error.*’)

2、关注B服务器发送的的所有日志,怎么办?

声明队列名称为“b-all-queue”并绑定到交换器上:channel. queueBind (b-all-queue’,’logs-change’,’ B.#’)或channel. queueBind (b-all-queue’,’logs-change’,’ B.*.*’)

3、关注所有服务器发送的email的所有日志,怎么办?

声明队列名称为“email-all-queue”并绑定到交换器上:channel. queueBind (email -all-queue’,’logs-change’,’ *.*.emal’)

4、想要接收所有日志:channel->queue_bind(‘all-log’,’logs-change’,’#’)

生产者:

public class TopicProducer {

public final static String EXCHANGE_NAME = "topic_logs";

public static void main(String[] args)
throws IOException, TimeoutException {
/**
* 创建连接连接到RabbitMQ
*/
ConnectionFactory factory = new ConnectionFactory();
// 设置MabbitMQ所在主机ip或者主机名
factory.setHost("127.0.0.1");

// 创建一个连接
Connection connection = factory.newConnection();

// 创建一个信道
Channel channel = connection.createChannel();
// 指定转发
channel.exchangeDeclare(EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);

/*日志消息,路由键最终格式类似于:info.order.B*/
String[] severities={"error","info","warning"};
for(int i=0;i<3;i++){
String[] modules={"user","order","email"};
for(int j=0;j<3;j++){
String[] servers={"A","B","C"};
for(int k=0;k<3;k++){
// 发送的消息
String message = "Hello Topic_["+i+","+j+","+k+"]";
String routeKey = severities[i%3]+"."+modules[j%3]
+"."+servers[k%3];
channel.basicPublish(EXCHANGE_NAME,routeKey,
null, message.getBytes());
System.out.println(" [x] Sent '" + routeKey +":'"
+ message + "'");
}
}

}
// 关闭频道和连接
channel.close();
connection.close();
}

}

消费者(ServerB的全部消息):

public class ServerBAllConsumer {

public static void main(String[] argv) throws IOException,
InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");

// 打开连接和创建频道,与发送端一样
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();

channel.exchangeDeclare(TopicProducer.EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();

channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"#.B");

System.out.println(" [*] Waiting for messages:");

// 创建队列消费者
final Consumer consumerA = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" AllConsumer Received "
+ envelope.getRoutingKey()
+ "':'" + message + "'");
}
};
channel.basicConsume(queueName, true, consumerA);
}
}

消费者(ServerA的ERROR消息):

// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();

channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"error.*.A");

System.out.println(" [*] Waiting for messages:");

消费者(所有的ERROR消息):

// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();

channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"error.#");

System.out.println(" [*] Waiting for messages:");

消费者(所有的EMAIl消息):

// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();

channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"*.email.*");

System.out.println(" [*] Waiting for messages:");

消费者(所有的消息):

// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();

channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME,
"#");

System.out.println(" [*] Waiting for messages:");