在上一篇中使用直接交换器改进了我们的系统,使得它能够有选择的进行接收消息,但它仍然有局限性——它不能基于多个条件进行路由。本节我们就进行能够基于多个条件进行路由的topics exchange学习。

发送给主题交换器的消息不能是任意的routing_key—它必须是一个单词列表,由点分隔。这些词可以是任意的,但通常它们指定与消息相关的一些特性。几个有效的路由示例:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit".。路由键中可以有任意多的字,最多可以有255个字节。

路由键也需要是相同的形式,topic交换器背后的逻辑类似于direct交换器——发送带有特定路由键的消息将被传送到绑定匹配路由键的所有队列中,

然而,有两个重要的特殊情况需要绑定键:

  • * (star) can substitute for exactly one word.                     星号可以代替一个词
  • # (hash) can substitute for zero or more words.               哈希可以代替零个或多个词
  • 通过下面的例子进行解释:
  • 在这个例子中,我们将发送所有描述动物的信息。消息将通过一个包含三个单词(两个点)的路由键发送。路径键中的第一个词将描述速度,第二个是颜色,第三个是物种:“<速度>.<颜色>.<物种>”。
  • We created three bindings: Q1 is bound with binding key "*.orange.*" and Q2 with "*.*.rabbit" and "lazy.#".

    These bindings can be summarised as:

  • Q1对所有的橙色动物都感兴趣。

  • Q2希望听到关于兔子的一切,以及关于懒惰动物的一切。

  • 设置了路由键为 "quick.orange.rabbit"的消息将被投递到两个队列,消息 "lazy.orange.elephant" 也被投递到他们两个,而"quick.orange.fox"将被投递到第一个队列,"lazy.brown.fox"仅被投递到第二个队列,"quick.brown.fox"没有匹配将被舍弃。

  • 通过上面的学习,我们知道,topic主题的交换器投递消息与redict交换器的不同在于,交换器类型和路由键的模糊匹配,现在我们就去把之前的代码进行改变,只需要将代码中的交换器类型改为topic,并将绑定的路由键更改一下,投递消息用的是确定的路由键,接收消息通过设置匹配的模糊绑定键,可以订阅到多条件的消息,接下来上代码,并将改动的代码以下划线形式标记出来。

  • 发送方代码:

  • package com.rabbitmq.HelloWorld;
    
    import java.io.IOException;
    import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory; public class Publish { private static final String EXCHANGE_NAME = "exchangeC"; public static void main(String[] args) throws IOException, TimeoutException {
    // TODO Auto-generated method stub
    // 创建工厂
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.10.185");
    factory.setUsername("admin");
    factory.setPassword("123456");
    factory.setPort(5672);
    // 创建连接
    Connection connetion = factory.newConnection();
    // 获得信道
    Channel channel = connetion.createChannel();
    // 声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct类型的交换器)
    channel.exchangeDeclare(EXCHANGE_NAME, "topic");
    String message = "555,2,2,33,66";
    // 发送消息,将第二项参数routingkey
    channel.basicPublish(EXCHANGE_NAME, "my.hello.haha", null, message.getBytes());
    System.out.println(" [x] Sent '" + message + "'");
    channel.close();
    connetion.close();
    } }
  • 接收方一:

  • package com.rabbitmq.HelloWorld;
    
    import java.io.IOException;
    import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.Consumer;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    import com.rabbitmq.client.AMQP.BasicProperties; public class Subscribe { private static final String EXCHANGE_NAME = "exchangeC";
    private static final String QUEUE_NAME = "queueA"; public static void main(String[] args) throws IOException, TimeoutException {
    // TODO Auto-generated method stub
    // 创建工厂
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.10.185");
    factory.setUsername("admin");
    factory.setPassword("123456");
    factory.setPort(5672);
    // 创建连接
    Connection connetion = factory.newConnection();
    // 获得信道
    Channel channel = connetion.createChannel();
    // 声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct的交换器)
    channel.exchangeDeclare(EXCHANGE_NAME, "topic");
    // 声明一个队列,在此采用临时队列
    String queueName = channel.queueDeclare().getQueue();
    // channel.queueDeclare(QUEUE_NAME, true, false, false, null);
    // 队列和交换器进行绑定,并设定路由键为error
    channel.queueBind(queueName, EXCHANGE_NAME, "my.#");
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
    Consumer consumer = new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope,
    BasicProperties properties, byte[] body) throws IOException {
    // TODO Auto-generated method stub
    String message = new String(body,"utf-8");
    System.out.println("[x] received'"+message+"'");
    }
    };
    channel.basicConsume(queueName, consumer);
    } }
  • 接收方二:

  • import java.io.IOException;
    import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.Consumer;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    import com.rabbitmq.client.AMQP.BasicProperties; public class Subscribe { private static final String EXCHANGE_NAME = "exchangeC";
    private static final String QUEUE_NAME = "queueA"; public static void main(String[] args) throws IOException, TimeoutException {
    // TODO Auto-generated method stub
    // 创建工厂
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.10.185");
    factory.setUsername("admin");
    factory.setPassword("123456");
    factory.setPort(5672);
    // 创建连接
    Connection connetion = factory.newConnection();
    // 获得信道
    Channel channel = connetion.createChannel();
    // 声明交换器(声明了一个名字位exchangeA,修改fanout类型为direct类型的交换器�?
    channel.exchangeDeclare(EXCHANGE_NAME, "topic");
    // 声明�?个队列,在此采用临时队列
    String queueName = channel.queueDeclare().getQueue();
    // channel.queueDeclare(QUEUE_NAME, true, false, false, null);
    // 队列和交换器进行绑定,未设定路由键
    channel.queueBind(queueName, EXCHANGE_NAME, "my.hello.*");
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
    Consumer consumer = new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope,
    BasicProperties properties, byte[] body) throws IOException {
    // TODO Auto-generated method stub
    String message = new String(body,"utf-8");
    System.out.println("[x] received'"+message+"'");
    }
    };
    channel.basicConsume(queueName, consumer);
    } }

    运行后,两个接收方均接收道理发送方发送的消息,尽管我们在两个接收方配置的绑定键并不相同,但是其模糊匹配规则均可以匹配到发送方发送消息的路由键,如果有大量接收方,我们就可以通过设置不同的绑定键来有选择的接收较多的消息或者是不接受消息。

官网英文版学习——RabbitMQ学习笔记(七)Topic的更多相关文章

  1. 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ

    鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...

  2. 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群

    在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...

  3. Unity shader 官网文档全方位学习(一)

    转载:https://my.oschina.net/u/138823/blog/181131 摘要: 这篇文章主要介绍Surface Shaders基础及Examples详尽解析 What?? Sha ...

  4. 利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)

    利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)   作者:王可利(Star·星星) 总结: 今天学习的jQ类库的使用,代码重复的比较多需要完善.严格区分大小写,在 $(" ...

  5. 官网英文版学习——RabbitMQ学习笔记(二)RabbitMQ安装

    一.安装RabbitMQ的依赖Erlang 要进行RabbitMQ学习,首先需要进行RabbitMQ服务的安装,安装我们可以根据官网指导进行http://www.rabbitmq.com/downlo ...

  6. 官网英文版学习——RabbitMQ学习笔记(三)Hello World!

    参考http://www.rabbitmq.com/tutorials/tutorial-one-java.html,我们直接上代码,由于我们的RabbitMQ服务是安装在虚拟机上的,具体参考上一节. ...

  7. 官网英文版学习——RabbitMQ学习笔记(八)Remote procedure call (RPC)

    在第四篇学习笔记中,我们学习了如何使用工作队列在多个工作者之间分配耗时的任务.   但是,如果我们需要在远程计算机上运行一个函数并等待结果呢?这是另一回事.这种模式通常称为远程过程调用或RPC.   ...

  8. 官网英文版学习——RabbitMQ学习笔记(五)Publish/Subscribe

    发布/订阅模式:把一个消息发送给多个消费者. 前几篇文章的思想是,我们好像看到了生产者将消息直接发送给queue,然后消费者也从queue中进行消费.其实并非如此,RabbitMQ中的消息传递模型的核 ...

  9. 官网英文版学习——RabbitMQ学习笔记(四)Work queues

    工作队列:把每个任务只发送给一个工作者. 上一篇我们是从一个指定的队列发送接收消息,在本文中,我们将创建一个工作队列,用于在多个工作者之间分配耗时的任务. 工作队列(即任务队列)背后的主要思想是避免立 ...

随机推荐

  1. luogu P2774 方格取数问题

    有限制的问题,显然考虑全选再根据限制去掉的想法较优,我们发现一个点四周的点受限,其x或者y差一,也就是说奇偶性不同,那我们可以将其分成白点和黑点,就变成了最小割的问题,将每个白点向受限制的黑点连边,c ...

  2. Day1-B-CF-1144B

    简述:有一个n个元素的序列,选奇数下一个就选偶数,偶数则下一个就是奇数,问能否取完,能取完输出0,否则输出能剩下的最小的之和 思路:统计奇偶数个数,若相等或相差一则取完,否则排列后取出最小的前x个(x ...

  3. Java连载78-深入自动拆装箱、Date类和SimpleDateFormat格式化

    一.深入自动拆装箱 1.直接举例: public class D78_AutomaticUnpackingAndPacking{ public static void main(String[] ar ...

  4. 「NOIP2017」逛公园

    传送门 Luogu 解题思路 考虑 \(\text{DP}\). 设 \(f[u][k]\) 表示从 \(u\) 到 \(n\) 走过不超过 \(Mindis(u, n) + k\) 距离的方案数. ...

  5. 学习JNA,Jnative

    首先说下JAVA调用DLL,Java调用DLL的常用方法大致为几种,JNI,JNA,Jnative等,但实现与易用性差距还是很大,1.JNI用的人比较多,但相对来说比较麻烦要熟悉c并且要使用javac ...

  6. 洛谷 P5242 [USACO19FEB]Cow Dating P

    这道题很有意思. 不难发现,对于一个区间 \([l, r]\),恰好只有一个奶牛接受邀请的概率为 \[\prod_{i=l}^r(1-p_i) \cdot \sum_{i=l}^r \frac {p_ ...

  7. 九 SpringMvc与json交互

    将json输出到页面: 1 加入jar包 2 配置Controller层,开启注解ResponseBody,将json发送到页面: 3 访问url 4 响应json,在形参列表里面加上注解

  8. Linux-使用之vim编译安装出现的问题

    ---恢复内容开始--- cd <directory> Short for "change directory". The shorthand name for the ...

  9. LeetCode206. Reverse Linked List(反转链表)

    题目链接:https://leetcode.com/problems/reverse-linked-list/ 方法一:迭代反转 https://blog.csdn.net/qq_17550379/a ...

  10. R语言作图 绘制中国地图

    参考:https://zhuanlan.zhihu.com/p/27360411 第一步.下载shapefile文件 一直都没有找到下载地址,死在了第一步 第二步.导入shp文件 第三步.画图