RabbitMQ (五) 主题
主题交换机
发送到主题交换机(topic exchange)的消息不可以携带随意什么样子的路由键(routing_key),它的路由键必须是一个由.分隔开的词语列表。这些单词随便是什么都可以,但是最好是跟携带它们的消息有关系的词汇。以下是几个推荐的例子:“stock.usd.nyse”, “nyse.vmw”, “quick.orange.rabbit”。词语的个数可以随意,但是不要超过 255 字节。
绑定键也必须拥有同样的格式。主题交换机背后的逻辑跟直连交换机很相似 —— 一个携带着特定路由键的消息会被主题交换机投递给绑定键与之想匹配的队列。但是它的绑定键和路由键有两个特殊应用方式:(就像正则匹配一样)
主题交换机
主题交换机是很强大的,它可以表现出跟其他交换机类似的行为
当一个队列的绑定键为 "#"(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。
当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为。
代码和上一个差不多,只是把direct
改为了topic
EmitLogTopic.java的代码
public class EmitLogTopic
{
private static final String EXCHANGE_NAME = "topic_logs";
public static final String[] TYPE = {"err.message", "info.critical", "warning.critical"};
public static void main(String[] args)
{
try
{
Connection connection = getConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
for (int i = 0; i < 3; i++)
{
//每一次发送一条不同严重性的日志
String severity = TYPE[i % 3];
// 发送的消息
String message = "Hello World" + i;
//参数1:exchange name
//参数2:routing key
channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
}
// 关闭频道和连接
channel.close();
connection.close();
} catch (IOException e)
{
e.printStackTrace();
} catch (TimeoutException e)
{
e.printStackTrace();
}
}
}
ReceiveLogsTopic.java的代码:
public class ReceiveLogsTopic
{
private static final String EXCHANGE_NAME = "topic_logs";
public static final String[] TYPE = {"*.critical"};
public static void main(String[] args)
{
try
{
Connection connection = getConnection();
// 打开连接和创建频道,与发送端一样
final Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
// 声明一个随机队列
String queueName = channel.queueDeclare().getQueue();
for (String severity : TYPE) {
//关注所有级别的日志(多重绑定)
channel.queueBind(queueName, EXCHANGE_NAME, severity);
}
System.out.println(" [*] Waiting for messages. ");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
});
} catch (IOException e)
{
e.printStackTrace();
} catch (TimeoutException e)
{
e.printStackTrace();
}
}
}