在上一篇中使用直接交换器改进了我们的系统,使得它能够有选择的进行接收消息,但它仍然有局限性——它不能基于多个条件进行路由。本节我们就进行能够基于多个条件进行路由的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. eclipse问题集合

    [eclipse更换jdk版本]

  2. shell 脚本通过Webhook 发送消息到微信群

    代码如下: #!/bin/sh # Filename: msg.sh # # Usage msg.sh "message text" # # 1. check if missing ...

  3. The way get information from mssql by using excel vba and special port

    Yes,  we can get information from mssql by using excel vba.  But the default port of MSSQL is  1433. ...

  4. SSM项目中,关于Test类中不能使用Autowired注入bean的问题

    在测试类中使用AutoWired注解一直不能获取到Bean,调用方法时一直报空指针异常,我有在其他类中使用AutoWired试了下,发现能够生效.问题应该就是处在Test类中,后面找了半天终于找到问题 ...

  5. Python正则表达式就是这么简单【新手必学】

    一前言本篇文章带大家快速入门正则表达式的使用,正则表达式的规则不仅适用python语言,基本大多数编程语言都适用,在日常使用中极为广泛,读者们有必要学好正则表达式.看完这篇文章,读者们要理解什么是正则 ...

  6. Py西游攻关之基础数据类型(六)-文件操作

    Py西游攻关之基础数据类型 - Yuan先生 https://www.cnblogs.com/yuanchenqi/articles/5782764.html 九 文件操作 9.1 对文件操作流程 打 ...

  7. springboot,vue,shiro整合 关于登录认证功能

    首先是session问题 传统session认证 http协议是一种无状态协议,即浏览器发送请求到服务器,服务器是不知道这个请求是哪个用户发来的.为了让服务器知道请求是哪个用户发来的,需要让用户提供用 ...

  8. Intent的常用属性之ComponentName

    启动activity的另一种方式 在按钮中添加如下代码 ComponentName componentName=new ComponentName(MainActivity.this,NewActiv ...

  9. JS - 数组转字符串

        var arr =['h','e','l','l','o']     var s = arr.join("");       console.log(s); 

  10. video-player

    1. VLC 2. MPlayer 3. FFmpeg 4. 显示媒体信息 5. 视频播放器软件比较 1. VLC https://www.videolan.org/vlc/ https://en.w ...