RabbitMQ---订阅模型-Topic

订阅模型-Topic

• Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!
• Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
• 通配符规则:
o #:匹配0或多个词(含零个)
o *:匹配不多不少恰好1个词(不含零个)
• 举例:
o audit.#:能够匹配audit.irs.corporate 或者 audit.irs
o audit.*:只能匹配audit.irs
RabbitMQ---订阅模型-Topic_第1张图片

• 在这个例子中,我们将发送所有描述动物的消息。消息将使用由三个字(两个点)组成的routing key发送。路由关键字中的第一个单词将描述速度,第二个颜色和第三个种类:“..”。
• 我们创建三个绑定:
Q1绑定了绑定键“* .orange.”,Q2绑定了“.*.rabbit”和“lazy.#”。
• Q1匹配所有的橙色动物。
• Q2匹配关于兔子以及懒惰动物的消息。
• 练习,生产者发送如下消息,会进入那个队列:

o	quick.orange.rabbit 
o	lazy.orange.elephant
o	quick.orange.fox 
o	lazy.pink.rabbit 
o	quick.brown.fox    
o	quick.orange.male.rabbit   
o	orange 

1、生产者

使用topic类型的Exchange,发送消息的routing key有3种: item.isnert、item.update、item.delete:

public class Send {
   private final static String EXCHANGE_NAME = "topic_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明exchange,指定类型为topic
       channel.exchangeDeclare(EXCHANGE_NAME, "topic");
       // 消息内容
       String message = "新增商品 : id = 1001";
       // 发送消息,并且指定routing key 为:insert ,代表新增商品
       channel.basicPublish(EXCHANGE_NAME, "item.insert", null, message.getBytes());
       System.out.println(" [商品服务:] Sent '" + message + "'");
       channel.close();
       connection.close();
   }
}

2、 消费者1

我们此处假设消费者1只接收两种类型的消息:更新商品和删除商品

public class Recv {
   private final static String QUEUE_NAME = "topic_exchange_queue_1";
   private final static String EXCHANGE_NAME = "topic_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明队列
       channel.queueDeclare(QUEUE_NAME, false, false, false, null);
       // 绑定队列到交换机,同时指定需要订阅的routing key。需要 update、delete
       channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.update");
       channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.delete");
       // 定义队列的消费者
       DefaultConsumer consumer = new DefaultConsumer(channel) {
           // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
           @Override
           public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                   byte[] body) throws IOException {
               // body 即消息体
               String msg = new String(body);
               System.out.println(" [消费者1] received : " + msg + "!");
           }
       };
       // 监听队列,自动ACK
       channel.basicConsume(QUEUE_NAME, true, consumer);
   }
}

3、消费者2

我们此处假设消费者2接收所有类型的消息:新增商品,更新商品和删除商品。

/**
* 消费者2
*/
public class Recv2 {
   private final static String QUEUE_NAME = "topic_exchange_queue_2";
   private final static String EXCHANGE_NAME = "topic_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明队列
       channel.queueDeclare(QUEUE_NAME, false, false, false, null);
       // 绑定队列到交换机,同时指定需要订阅的routing key。订阅 insert、update、delete
       channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.*");
       // 定义队列的消费者
       DefaultConsumer consumer = new DefaultConsumer(channel) {
           // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
           @Override
           public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                   byte[] body) throws IOException {
               // body 即消息体
               String msg = new String(body);
               System.out.println(" [消费者2] received : " + msg + "!");
           }
       };
       // 监听队列,自动ACK
       channel.basicConsume(QUEUE_NAME, true, consumer);
   }
}

4、测试

RabbitMQ---订阅模型-Topic_第2张图片

RabbitMQ---订阅模型-Topic_第3张图片

你可能感兴趣的:(Spring,Cloud,java-rabbitmq,rabbitmq,java)