RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)

文章目录

  • 0. 基础知识
  • 1. 安装
  • 2. 各种工作模式介绍(并编写代码)
    • 1. 简单模式(Hello World)
    • 2. 工作队列模式(Work queues)
    • 3. 订阅模式(Pub/Sub)
      • 1. 广播模式(Fanout)
      • 2. 路由模式(定向路由DIRECT)
      • 3. 通配符模式(Topic)
  • 其他文章
  • RabbitMQ(一)-----MQ基础知识点
  • RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)
  • RabbitMQ(三)-----非常详细Springboot整合步骤
  • RabbitMQ(四)-----高级应用(消息可靠性投递,消费端限流,TTL,死信队列,延迟队列)
  • RabbitMQ(五)-----集群搭建

0. 基础知识

  1. RabbitMQ 是基于 AMQP 协议使用 Erlang 语言开发的一款消息队列产品。

  2. AMQP协议类似http协议,是一个网络协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

  3. 基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。

  4. AMQP协议 Advanced Message Queuing Protocol(高级消息队列协议)。

  5. RabbitMQ基于 AMQP 协议实现,架构图如下
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第1张图片

    1. producer:是生产者,即生成消息的。
    2. consumer:是消费者,即接受消息的。
    3. Broker:接收和分发消息的应用,RabbitMQ Server就是 Message Broker。
    4. Connection:publisher/consumer 和 broker 之间的 TCP 连接。
    5. Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接, Channel 之间又是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
    6. VirtualHost:虚拟主机,每个虚拟主机里面有很多Exchange、Queue,每个虚拟主机相互隔离,完成逻辑分区,类似于mysql中每个database,里面有可以有很多表,不同database中的表相互隔离。
    7. Queue:队列,消息存储在队列中,被消费者取走。
    8. Exchange:交互机,接收生产者发送的消息,只负责转发消息,不具备存储消息能力,根据路由规则转发消息给相应队列,如果无队列与其绑定,或无符合路由规则队列,则消息会丢失。
    9. Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key(路由键)。Binding 信息被保存到 exchange 中的查询表中,用于消息的分发依据。

1. 安装

  1. Ubuntu中使用docker安装:https://blog.csdn.net/xueyijin/article/details/117673546
  2. Ubuntu中apt-get install安装方式:https://blog.csdn.net/haeasringnar/article/details/82715823
  3. win10中安装:https://blog.csdn.net/xueyijin/article/details/117114046

2. 各种工作模式介绍(并编写代码)

  1. 我们知道RabbitMQ基于 AMQP 协议实现,因此下面将使用amqp client进行代码演示学习。

  2. 自行创建两个工程,一个为producer生产者,一个为consumer消费者。如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第2张图片

  3. 两个工程都导入jar包,如下:

    <dependencies>
            <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
            <dependency>
                <groupId>com.rabbitmq</groupId>
                <artifactId>amqp-client</artifactId>
                <version>5.12.0</version>
            </dependency>
    
    </dependencies>
    

1. 简单模式(Hello World)

  1. 简单模式:有一个生产者,一个消费者,一个消息队列。生产者将消息发送给队列,消息队列可以缓存消息,消费者可从中取出消息。

  2. 简单模式模型如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第3张图片

  3. 代码如下:
    简单模式生产者代码

    /**
     * @author JIN
     * @description 简单模式 一个生产者 一个消费者 一个消息队列
     * @createTime 2021-06-10 10:18
     **/
    public class HelloWorld {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            // 设置一系列内容
            // ip
            connectionFactory.setHost("127.0.0.1");
            // 端口
            connectionFactory.setPort(5672);
            // 名字
            connectionFactory.setUsername("jin");
            // 密码
            connectionFactory.setPassword("jin");
            // 虚拟主机
            connectionFactory.setVirtualHost("/jin");
            // 建立连接
            Connection connection = connectionFactory.newConnection();
            // 获取channel
            Channel channel = connection.createChannel();
    
            // queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments)
            // 参数意思:
            // queue 队列名字
            // durable 是否持久化
            // exclusive 是否独占,true为 独占,只有一个消费者监听这个队列,且当connection关闭时,自动删除此队列
            // autoDelete 是否自动删除,当没有消费者consumer监听队列时,队列自动删除
            // arguments 其他参数
            // 下面一句代码---用于创建队列
            channel.queueDeclare("HelloWorldQueue",true, false,true,null);
    
            // basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
            // exchange 交换机,这里是简单模式,没有交换机,因此只需要写空 ""
            // routingkey 路由键,在rabbitmq简单模式中 消息队列名字默认就是路由键
            // props 其他额外参数 可以填null
            // body 具体消息内容
            // 下面代码 是生产者向 rabbitmq 发送消息
            channel.basicPublish("","HelloWorldQueue",null,"HelloWorld的测试".getBytes());
    
            //关闭资源
            channel.close();
            connection.close();
        }
    }
    
  4. RabbitMQ Management 查看
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第4张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第5张图片

  5. 简单模式消费者代码

    /**
     * @author JIN
     * @description 简单模式 消费者
     * @createTime 2021-06-10 10:33
     **/
    public class HelloWorld {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            // 下面一句代码---用于创建队列,由于生产者已经生产,下面可有可无
            // 深入解析:
            // 1. 若一开始你队列为空,你先执行生产者代码,生产者必须有创建队列代码,消费者可有可无
            // 2. 若一开始你队列为空,你先执行消费者代码,消费者必须有创建队列代码,生产者可有可无
            channel.queueDeclare("HelloWorldQueue",true, false,true,null);
    
    
    
            // basicConsume(String queue, boolean autoAck, Consumer callback)
            // 参数说明:
            // 1. queue 监听的队列
            // 2. autoAck 是否自动确认,当消费者收到一个消息,自动给rabbitmq发送已经收到的确认信息
            // 3. callback 回调函数,当消费者收到消息,执行对应操作
            // 下面代码 是消费者从队列获取消息
            channel.basicConsume("HelloWorldQueue",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    // 参数说明
                    // consumerTag 消息tag,每个消息都有自己的tag
                    // envelope 可以获得路由键信息,交换机信息等
                    // envelope.getExchange();
                    // envelope.getRoutingKey();
                    // properties 其他参数配置
                    // body 收到的信息
                    System.out.println(new String(body));
                }
            });
    
            //因为消费者需要一直监听队列是否有消息,因此无需关闭资源
        }
    }
    

    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第6张图片

2. 工作队列模式(Work queues)

  1. 工作队列模式:相对简单模式来说,就是多了一些消费者,多个消费者共同消费同一个队列中的消息(是竞争关系),应用场景通常是对于任务过重或者任务较多情况使用工作队列模式可以提高任务处理的速度。

  2. 工作队列模式模型如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第7张图片

  3. 消费者代码
    因为为了演示多个消费者相互竞争同一个队列的消息,先将2个消费者启动,然后再让生产者发送消息。

    /**
     * @author JIN
     * @description  消费者一号
     * @createTime 2021-06-10 10:51
     **/
    public class WorkQueueConsumer1 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.queueDeclare("WorkQueue",true, false,true,null);
    
            channel.basicConsume("WorkQueue",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者一号:    " + new String(body));
                }
            });
    
        }
    }
    
    /**
     * @author JIN
     * @description 消费者二号
     * @createTime 2021-06-10 10:51
     **/
    public class WorkQueueConsumer2 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.queueDeclare("WorkQueue",true, false,true,null);
    
            channel.basicConsume("WorkQueue",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者二号:    " + new String(body));
                }
            });
    
        }
    }
    
  4. 生产者代码

    /**
     * @author JIN
     * @description workqueue模式,一个队列,一个生产者,多个消费者
     * @createTime 2021-06-10 10:48
     **/
    public class WorkQueue {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.queueDeclare("WorkQueue",true, false,true,null);
            for (int i = 1; i <= 10; i++) {
                // 为了演示 多个消费者竞争同一个队列 消息,因此发送多个消息
                channel.basicPublish("","WorkQueue",null,("消息编号:" + i + " , WorkQueue的测试").getBytes());
            }
    
            channel.close();
            connection.close();
        }
    }
    
  5. 结果图
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第8张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第9张图片

3. 订阅模式(Pub/Sub)

  1. 在之前的两种模式中,都是一个消息只能发送到一个队列中,只能被消费一次,而从订阅模式开始则可以一个消息被多个消费者消费了
  2. 订阅模式:比之前的模式,添加了exchange交换机,交换机负责转发消息到队列中。
  3. 订阅模式模型图:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第10张图片
  4. 生产者:将不在直接发送消息给队列了,而是将消息发送给交换机
  5. 交换机:一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。
  6. Exchange有常见以下3种类型
    1. Fanout:广播,将消息交给所有绑定到交换机的队列
    2. Direct:定向,把消息交给符合指定routing key 的队列
    3. Topic:通配符,把消息交给符合routing pattern(路由模式)的队列

1. 广播模式(Fanout)

  1. 广播模式就是将消息交给所有绑定到交换机的队列。

  2. 广播模式模型如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第11张图片

  3. 生产者代码

    /**
     * @author JIN
     * @description  广播模式,一个交换机,一个生产者,两个队列 两个消费者
     * @createTime 2021-06-10 12:14
     **/
    public class Fanout {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            // 创建2个队列
            channel.queueDeclare("Fanout-Queue-01", true,false,true,null);
            channel.queueDeclare("Fanout-Queue-02", true,false,true,null);
    
            // 创建交换机
            // exchangeDeclare(String exchange, BuiltinExchangeType type)
            // 参数说明:
            // 1. exchange 交换机
            // 2. type 交换机类型
            // BuiltinExchangeType.FANOUT 广播
            // BuiltinExchangeType.DIRECT 定向
            // BuiltinExchangeType.TOPIC  通配符
            channel.exchangeDeclare("Fanout-Exchange", BuiltinExchangeType.FANOUT);
    
            // 交换机与队列进行绑定
            // queueBind(String queue, String exchange, String routingKey)
            // 参数说明:
            // 1. queue 队列名字
            // 2. exchange 交换机名字
            // 3. 绑定的路由键,由于这里是广播,全部队列都收到消息,即填"" 即可
            channel.queueBind("Fanout-Queue-01","Fanout-Exchange","");
            channel.queueBind("Fanout-Queue-02","Fanout-Exchange","");
    
    
            for (int i = 0; i < 5; i++) {
                // 发送消息
                // 由于是广播,无需route-key
                channel.basicPublish("Fanout-Exchange","",null,"Fanout测试".getBytes());
            }
    
            channel.close();
            connection.close();
        }
    }
    
  4. 消费者代码

    public class FanoutConsumer1 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            // 创建2个队列
            // 由于生产者写了,这里可有可无
            channel.queueDeclare("Fanout-Queue-01;", true,false,true,null);
            channel.queueDeclare("Fanout-Queue-02;", true,false,true,null);
    
            channel.basicConsume("Fanout-Queue-01",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者一号:  "  + new String(body));
                }
            });
    
        }
    }
    
    public class FanoutConsumer2 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            // 创建2个队列
            // 由于生产者写了,这里可有可无
            channel.queueDeclare("Fanout-Queue-01;", true,false,true,null);
            channel.queueDeclare("Fanout-Queue-02;", true,false,true,null);
    
            channel.basicConsume("Fanout-Queue-02",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者二号:  "  + new String(body));
                }
            });
    
        }
    }
    
    
  5. 结果图:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第12张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第13张图片
    从上面截图可以知道,每个消费者都消费了5次,并没有想work queue模式一样处于竞争关系,是因为work queue 模式是一个队列对应两个消费者,而Pub/Sub模式是,一个消费者对应一个队列,自己监听自己的队列,而队列是否有消息得看交换机是否转发过去,而对于同一个消息,交换机可以转发到符合路由规则的队列

2. 路由模式(定向路由DIRECT)

  1. 定向模式:

    1. 队列与交换机的绑定,不能是任意绑定了,而是要指定一个 RoutingKey(路由key)
    2. 消息的发送方在向 Exchange 发送消息时,也必须指定消息的 RoutingKey
    3. Exchange 不再把消息交给每一个绑定的队列,而是根据消息的 Routing Key 进行判断,只有队列的Routingkey 与消息的 Routing key 完全一致,才会接收到消息。
  2. 定向模式模型图:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第14张图片

    1. 生产者,向Exchange发送消息的时候,需要指定一个routing key。
    2. 交换机,接收到的消息,需要交给与routing key完全匹配的队列。
    3. C1消费者,其所在队列指定了需要 routing key 为 error 的消息。
      C2消费者,其所在队列指定了需要 routing key 为 info、error、warning 的消息
  3. 生产者代码

    /**
     * @author JIN
     * @description
     * @createTime 2021-06-10 12:46
     **/
    public class Direct {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            // 创建2个队列
            channel.queueDeclare("Direct-Queue-01", true,false,true,null);
            channel.queueDeclare("Direct-Queue-02", true,false,true,null);
            // 创建交换机
            channel.exchangeDeclare("Direct-Exchange", BuiltinExchangeType.DIRECT);
            // 绑定交换机与队列
            // 队列1 将会收到 路由建为 DIRECT.error 的消息
            channel.queueBind("Direct-Queue-01","Direct-Exchange","DIRECT.error");
            // 队列2 将会收到 路由建为 DIRECT.add 的消息
            channel.queueBind("Direct-Queue-02","Direct-Exchange","DIRECT.add");
    
            // 发送了三条消息
            channel.basicPublish("Direct-Exchange","DIRECT.error",null,"我是error消息".getBytes());
            channel.basicPublish("Direct-Exchange","DIRECT.add",null,"我是add消息".getBytes());
            channel.basicPublish("Direct-Exchange","DIRECT.info",null,"我是info消息".getBytes());
    
    
            channel.close();
            connection.close();
        }
    }
    
  4. 消费者代码

    /**
     * @author JIN
     * @description 消费者一号 接受队列1的消息,即只接受 routing key 为 error的消息
     * @createTime 2021-06-10 12:51
     **/
    public class DirectConsumer1 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Direct-Queue-01",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者一号:  "  + new String(body));
                }
            });
        }
    }
    
    /**
    	 * @author JIN
    	 * @description 消费者二号 接受队列2的消息,即只接受 routing key 为 add的消息
    	 * @createTime 2021-06-10 12:51
    	 **/
    public class DirectConsumer2 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Direct-Queue-02",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者二号:  "  + new String(body));
                }
            });
        }
    }
    
  5. 结果截图
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第15张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第16张图片
    我们在生产者的时候发送了三条消息,未出现routing key为 DIRECT.info的消息,因为没有符合的队列,被交换机舍去了。

3. 通配符模式(Topic)

  1. 如果现在有个需求,要求把系统各个模块的error错误信息放在同一个队列,那么按照上面定向模式,则需要建立大量的交换机跟队列的路由键,比如:order.error,login.error…等等,实在是很麻烦,因此诞生出了通配符模式。

  2. 通配符模式模型如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第17张图片

    1. 如上图,交换机使用的是通配符方式,通配符的符号有两种:
      ‘#’ 代表 占位 0个或者多个词
      ‘*’ 代表 占位1个词
      具体下面例子说明
    2. 根据上面的图来说明:
      1. routing key 为 Lazy 、或Lazy.error、或Lazy.kkk.nnn.bbb 都可以进入Q2队列。
        Lazy.# 代表 以 Lazy 开头的 routing key
      2. routing key 为aa.bb.rabbite、或aaaa.kkkk.rabbite都可以进入Q2队列。
        但是 aaa.bbb.ccc.rabbite 或者 rabbite 无法进入Q2队列
        因为 * 仅仅代表占位一个词
      3. routing key 为a.orange.b 、或akbkdi.orange.bbilk 都可以进入Q1队列。
        但是 a.b.c.orange.d 或者 orange 都无法进入Q1队列。
  3. 生产者代码

    public class Topic {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
    
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.queueDeclare("Topic-Queue-01",true,false,true,null);
            channel.queueDeclare("Topic-Queue-02",true,false,true,null);
            channel.queueDeclare("Topic-Queue-03",true,false,true,null);
            channel.queueDeclare("Topic-Queue-04",true,false,true,null);
    
    		// 第三个参数 是否持久化
            channel.exchangeDeclare("Topic-Exchange", BuiltinExchangeType.TOPIC,true);
    		// 创建这么多队列,只是为了* # 的演示
            channel.queueBind("Topic-Queue-01","Topic-Exchange","*.add");
            channel.queueBind("Topic-Queue-02","Topic-Exchange","#.add");
            channel.queueBind("Topic-Queue-03","Topic-Exchange","*.*");
            channel.queueBind("Topic-Queue-04","Topic-Exchange","#.#");
    
            channel.basicPublish("Topic-Exchange","Hello.add",null,"我是Hello.add消息".getBytes());
            channel.basicPublish("Topic-Exchange","Hello.World.add",null,"我是Hello.World.add消息".getBytes());
            channel.basicPublish("Topic-Exchange","add",null,"我是add消息".getBytes());
    
            channel.close();
            connection.close();
    
        }
    }
    
  4. 消费者代码(共四个,因为在生产者中我创建了4个队列)

    public class TopiceConsumer1 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Topic-Queue-01",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者一号(*.add):  "  + new String(body));
                }
            });
        }
    }
    
    public class TopiceConsumer2 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Topic-Queue-02",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者二号(#.add):  "  + new String(body));
                }
            });
        }
    }
    
    public class TopiceConsumer3 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Topic-Queue-03",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者三号(*.*):  "  + new String(body));
                }
            });
        }
    }
    
    public class TopiceConsumer4 {
        public static void main(String[] args) throws IOException, TimeoutException {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("jin");
            connectionFactory.setPassword("jin");
            connectionFactory.setVirtualHost("/jin");
            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.basicConsume("Topic-Queue-04",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("我是消费者四号(#.#):  "  + new String(body));
                }
            });
        }
    }
    
  5. 结果图
    生产者只发送了三个消息,结果如下:
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第18张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第19张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第20张图片
    RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)_第21张图片

其他文章

RabbitMQ(一)-----MQ基础知识点

RabbitMQ(二)-----rabbitMq基础知识与工作模式(代码演示)

RabbitMQ(三)-----非常详细Springboot整合步骤

RabbitMQ(四)-----高级应用(消息可靠性投递,消费端限流,TTL,死信队列,延迟队列)

持续更新中

RabbitMQ(五)-----集群搭建

持续更新中

你可能感兴趣的:(RabbitMQ,rabbitmq,交换机,队列,java)