Topic
在之前的一篇教程中,我们改进了日志系统。我们使用direct
直接广播,而不是使用fanout
,从而获得了选择性接收日志的可能性。
虽然使用direct exchange
改进了我们的系统,但它任然有局限性–它不能基于多个标准进行路由。
Topic exchange
消息发送到topic exchange
不能是一个随意的routing-key
。它必须是一个由.
分割单纯列表。
例如stock.usd.nyse
、nyse.vmw
、quick.orange.rabbit
等。routing-key
可以有尽可能多,但是最多255字节。
绑定键必须采用相同的形式。topic exchange
和direct exchange
类似-使用特定routig key
发送的消息会被传递到匹配binding key
的队列里面。但是,对于routing key
有两个特殊情况
*
(star)可以替代一个单词#
(hash) 可以代替0个或多个单词
Topic exchange
Topic exchange是非常厉害的并且可以表现和其他exchange一样的
当一个队列是用
#
绑定,那么就会接受到所有信息,不管routing-key是什么,就像fanout当绑定中不使用
*
和#
等特殊字符,topic exchange就会像direct exchange
Sender.java
public class Send {
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//声明exchange
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
// 消息内容
String msg = "hello world!";
channel.basicPublish(EXCHANGE_NAME,"routekey1.1",null,msg.getBytes());
channel.close();
connection.close();
}
}
Rece1.java
public class Rece1 {
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//
String queueName = channel.queueDeclare().getQueue();
// // 声明队列
// channel.queueDeclare(queueName,false,false,false,null);
//绑定队列到交换机上
channel.queueBind(queueName,EXCHANGE_NAME,"routekey.*");
//同一时刻服务器只发送一条消息
channel.basicQos(1);
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("rece1 :" + msg);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("rece1 done");
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
channel.basicConsume(queueName,false,consumer);
}
}
Rece2.java
public class Rece2 {
private final static String QUEUE_NAME = "test_queue_topic_work_2";
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//绑定队列到交换机上
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"*.*");
//同一时刻服务器只发送一条消息
channel.basicQos(1);
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("rece1 :" + msg);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("rece1 done");
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}