RabbitMQ中几种基本队列模式的讲解,附代码~~~

基本概念
  • RabbitMQ也可以叫做消息队列,用来作为中间件
    • 优点
      • 解耦
      • 异步
      • 削峰
    • 和其他中间件相比,不容易丢失数据,高可用,性能相比Kafka来说中规中举,但是数据的完整性比Kafka强,比较适合中小项目使用。

运行RabbitMQ

  • 初始的队列如下
    rabbitmq的初始界面

入门案例

  • 导入依赖
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.6.0</version>
        </dependency>
简单队列模式

就突出两个字,简单,生产者往队列里塞消息,消费者往队列里面取消息,其他啥的也不管。

例子:

  • 消息生产者的定义
    • 1.定义队列的名称
    • 2.创建连接工厂的对象(ConnectionFactory)
    • 3.根据连接工厂的对象获取连接
    • 4.根据获取到的连接创建信道
    • 5.通过信道绑定队列
    • 6.定义要发送的消息
    • 7.通过信道发送消息
    • 8.关闭连接和信道
package send;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

public class Send {
    //1.声明队列名称
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (
                //3.根据连接工厂获取连接
                Connection connection = factory.newConnection();
                //4.根据连接创建信道
                Channel channel = connection.createChannel()) {
            /*
              5.通过信道绑定队列
             @Param1 队列的名称
              @Param2 持久化
             @Param3 排他队列(仅对首次声明他的链接可见,如果链接关掉了,排他队列的值也会被删掉)
              @Param4 自动删除
              @Param5 自己携带的参数
             */
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            //6
            String message = "Hello World!";

            /*7.通过信道发送消息到队列
             *  @Param1 交换机
             * @Param2 队列名称
             * @Param3 自己附带的参数
             * @Param4 消息的实体
             */
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}

启动消息生产者。
在这里插入图片描述
这里可以看到我们的队列中多了一个hello队列,且里面有一条消息没有被消费。

  • 消息消费者的定义
    • 1.定义队列的名称
    • 2.创建连接工厂的对象(ConnectionFactory)
    • 3.根据连接工厂的对象获取连接
    • 4.根据获取到的连接创建信道
    • 5.通过信道绑定队列
    • 6.监听消息队列 回调消费消息
package accept;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import java.nio.charset.StandardCharsets;

public class Recv {
    //1.声明队列名称
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听消息队列
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}

启动消息消费者。
在这里插入图片描述
我们发现hello队列中的消息被消费掉了。这就是简单队列。优点就是简单,但是缺点就很多啦。
生产者只管生产,消费者只管消费,没有考虑到消费者的消费能力问题。
大家想一下,如果生产者一天生产500条消息,但是我们的消费者一天只能消费100条消息,这样下去是不是每天都要积压四百条数据,是不是会导致一些消息永远也不会被消费,而且队列长度越来越长,占用的内存越来越大,最后就是宕机的结果。
那怎么解决这种问题?产力过剩我们增加消费者就好了,比如我们在增加4个消费者,那就是五个消费者。五个消费者就能消费完这500条消息。增加消费者就变成了工作队列。

工作队列

工作队列有两种模式,轮询和公平。
轮询就是字面上的意思,就是当有多个消费者存在时,每人消费一条的来,我消费了到你,你消费了到我。

  • 实现轮询
    给定两个消费者(减慢消费速度),一个生产者
    消费者1
package work.accept;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

import java.nio.charset.StandardCharsets;

/**
 * 工作队列--轮询--消费者
 */
public class Recv {
    //1.声明队列名称
    private final static String QUEUE_NAME = "work_poll";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            //模拟消费消息慢的场景
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
            //手动确认消息,即使我收到了多条消息,我也一条一条的去手动确认
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
        };
        //6.监听消息队列
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });
    }
}

消费者2

package work.accept;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

import java.nio.charset.StandardCharsets;

/**
 * 工作队列-  轮询---消费者1
 */
public class Recv1 {
    //1.声明队列名称
    private final static String QUEUE_NAME = "work_poll";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            //模拟消费消息慢的场景
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
            //手动确认消息,即使我收到了多条消息,我也一条一条的去手动确认
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
        };
        //6.监听消息队列
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });
    }
}

生产者

package work.send;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

/**
 * 工作队列 ---轮询--生产者
 */

public class Send {
    //1.声明队列名称
    private final static String QUEUE_NAME = "work_poll";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (
                //3.根据连接工厂获取连接
                Connection connection = factory.newConnection();
                //4.根据连接创建信道
                Channel channel = connection.createChannel()) {
            /*
              5.通过信道绑定队列
             @Param1 队列的名称
              @Param2 持久化
             @Param3 排他队列(仅对首次声明他的链接可见,如果链接关掉了,排他队列的值也会被删掉)
              @Param4 自动删除
              @Param5 自己携带的参数
             */
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);


            //生产者生产20条消息
            for (int i = 0; i < 20; i++) {
                //6
                String message = "Hello World!"+i;
                /*7.通过信道发送消息到队列
                 *  @Param1 交换机
                 * @Param2 队列名称
                 * @Param3 自己附带的参数
                 * @Param4 消息的实体
                 */
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println(" [x] Sent '" + message + "'"+i);
            }

        }
    }
}

依次运行消费者1,消费者2,生产者,我们可以通过控制台观察两个消费者的消费情况,如下,
在这里插入图片描述
这就是工作队列中的轮询模式,主要解决生产者的生产能力远远大于消费者的消费能力时,防止消息积累的问题。

  • 公平模式(工作队列)
    • 轮询模式的效率不高,当两个消费者消费能力差距过大时,先消费完的得等着,造成一种资源的浪费,消费时间过长等问题。
    • 所以公平模式就是说,如果有先消费完了的消费者,则先消费完的消费者去帮没有消费完的消费者消费它的任务,尽你所能的去消费,所以这个公平和我们生活中的公平是不一样的,这里的公平模式是能力越强,责任越大。
    • 公平模式的设置非常简单,就是不让他们提前去分配消息,限制消费者处理完当前的消息再去消费消息,这样速度快的就会多消费,速度慢的就会少消费。整体上就不会出现等和资源的浪费,减短了整体的消费时间。
    • 怎么设置公平模式?在消费者中添加一下代码即可。
            //限制消费者每次只能接收一条消息,处理完才能接受下一条
            int prefetchCount=1;
            channel.basicQos(prefetchCount);
            ava

其余的代码和轮询案例中的一样,只需要在消费者中加入这个限设置即可从轮询模式转变为公平模式。

发布-订阅队列

当我们的需求越来越复杂,前面两种模式就不能满足我们的需求了,通过案例我们可以看到,前面的两种模式,消费者是不可能拿到重复的数据的。前面两种模式是如果消息已经被消费者消费了,那么其他消费者就去消费其他的消息,是不可能拿到和其他消费者相同的一个消息的,
那现在如果我想要让所有的消费者都收到我发出去的同一条信息,那我们应该怎么实现呢,没错,就是现在要说的发布-订阅队列模式。
怎么实现?借助交换机,生产者生产的消息,会先发送到交换机中,在由交换机将生产者生产的数据分发给队列,然后监听每个队列的消费者就会获取到交换机转发到队列中的数据,这样所有的队列拿到的数据都是由交换机转发的相同数据。
大致如图
在这里插入图片描述
代码实现:
消费者实现步骤:

  • 定义交换机名称(使用广播类型)
  • 创建连接工厂
  • 设置主机地址
  • 通过连接工厂获取连接
  • 获取连接之后开启信道(channel)
  • 绑定交换机(channel.exchangeDeclare())
  • 查询交换机中队列的名称(channel.queueDeclare().getQueue())
  • 将交换机和队列进行绑定(chanel.queueBind())
  • 监听队列

代码如下

package exchange.accept;

import com.rabbitmq.client.*;

import java.nio.charset.StandardCharsets;

/**
 * 发布/订阅--消费者
 */
public class Recv1 {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_fanout";
    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
        //6.获取交换机生成的队列名称(排他队列)
        String byNameQueue = channel.queueDeclare().getQueue();
        //7. 将队列和交换机进行绑定
        channel.queueBind(byNameQueue,EXCHANGE_NAME,"");
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听通过交换机得到的消息队列
        channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
    }
}

相同的代码再次创建一个消费者
发布/订阅生产者步骤:

  • 定义交换机名称(使用广播类型)
  • 创建连接工厂
  • 设置主机地址
  • 通过连接工厂获取连接
  • 获取连接之后开启信道(channel)
  • 绑定交换机(channel.exchangeDeclare())
  • 上传消息到交换机

发布/订阅 生产者代码如下:

package exchange.send;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

/**
 * 订阅、发布 ---生产者
 */

public class Send {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_fanout";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (
                //3.根据连接工厂获取连接
                Connection connection = factory.newConnection();
                //4.根据连接创建信道
                Channel channel = connection.createChannel()) {
                //5.绑定带交换机                         //Fanout交换机的类型(广播模式)
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
                
                String message = "Hello World!";
                channel.basicPublish( EXCHANGE_NAME, "",null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println(" [x] Sent '" + message + "'");
            }

        }
    }

先运行两个消费者,让他们监听队列,然后在运行生产者,不出意外两个消费者会收到相同的消息。
在这里插入图片描述

路由队列

刚说完发布/订阅队列,这就又来问题了,发布/订阅队列是通过交换机向不同的队列推送数据。那我现在如果说,我不想要所有人都可以接受到我的消息,我只想给部分消费者发送消息,怎么实现?
使用路由队列,在绑定交换机和队列的时候,通过路由key(routin key)的参数设置交换机转发的路由,使得交换机可以根据路由转发消息(交换机是直连模式)。
重点看代码,代码中有相应的注释:

路由队列:生产者


package direct.send;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

/**
 * 路由队列 ---生产者
 */

public class Send {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_direct";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (
                //3.根据连接工厂获取连接
                Connection connection = factory.newConnection();
                //4.根据连接创建信道
                Channel channel = connection.createChannel()) {
                //5.绑定带交换机                         //Fanout交换机的类型(广播模式)
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

                String infoMessage = "普通信息!";
                String errorMessage = "错误信息!";
                String warningMessage = "警告信息!";
                //路由信息
                String infoRoutingKey = "info!";
                String errorRoutingKey = "error!";
                String warningRoutingKey = "warning!";

                //发送信息,并且携带路由的key
                channel.basicPublish( EXCHANGE_NAME, infoRoutingKey,null, infoMessage.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish( EXCHANGE_NAME, errorRoutingKey,null, errorMessage.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish( EXCHANGE_NAME, warningRoutingKey,null, warningMessage.getBytes(StandardCharsets.UTF_8));

                System.out.println(" [x] Sent '" + infoMessage + "'");
                System.out.println(" [x] Sent '" + errorMessage + "'");
                System.out.println(" [x] Sent '" + warningMessage + "'");
            }

        }
    }

只能访问错误数据的消费者

package direct.accept;

import com.rabbitmq.client.*;

import java.nio.charset.StandardCharsets;

/**
 * 路由队列--消费者
 */
public class Recv {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_direct";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //6.获取交换机生成的队列名称(排他队列)
        String byNameQueue = channel.queueDeclare().getQueue();
        //7. 将队列和交换机进行绑定同时绑定路由
        String errorRoutingKey = "error!";
        channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey); //该路由表示当前消费者只能接收错误的信息
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听通过交换机得到的消息队列
        channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
    }
}

三个路径都可以访问的消费者

package direct.accept;

import com.rabbitmq.client.*;

import java.nio.charset.StandardCharsets;

/**
 * 路由队列--消费者
 */
public class Recv1 {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_direct";
    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //6.获取交换机生成的队列名称(排他队列)
        String byNameQueue = channel.queueDeclare().getQueue();
        //7. 将队列和交换机进行绑定同时绑定路由
        String infoRoutingKey = "info!";
        String errorRoutingKey = "error!";
        String warningRoutingKey = "warning!";
        channel.queueBind(byNameQueue,EXCHANGE_NAME,infoRoutingKey); //表示可以当前的消费者可以获取这三个路由下的内容。
        channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey);
        channel.queueBind(byNameQueue,EXCHANGE_NAME,warningRoutingKey);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听通过交换机得到的消息队列
        channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
    }
}

运行生产者,可以看见提交了三个信息,同时给这三个信息设置了路由:

在这里插入图片描述


很清楚的看到,两个消费者一个获取了三个信息,一个只获得了错误信息,这就是路由队列。

主题队列

路由队列虽然定制性强,但是当我们的项目越来越庞大的时候,相应的路由key就越来越多,难以维护和管理。
所以主题队列就是为了解决改善这一问题,它是在路由队列的基础上,在绑定路由key的时候,将写死的路由变成了正则表达式。前提交换机要更改为topic模式,且生产数据时要传递完整的路由名称,生产数据时不可以使用正则表达式(*表示可以匹配一个路由key,#表示可以匹配多个路由key)。

消费者:

package topic.accept;

import com.rabbitmq.client.*;

import java.nio.charset.StandardCharsets;

/**
 * 主题队列-消费者
 */
public class Recv {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_topic";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //6.获取交换机生成的队列名称(排他队列)
        String byNameQueue = channel.queueDeclare().getQueue();
        //7. 将队列和交换机进行绑定同时绑定路由

        String errorRoutingKey = "#.message.#";
        channel.queueBind(byNameQueue,EXCHANGE_NAME,errorRoutingKey); //该路由表示当前消费者只能接收错误的信息
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听通过交换机得到的消息队列
        channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
    }
}

消费者2

package topic.accept;

import com.rabbitmq.client.*;

import java.nio.charset.StandardCharsets;

/**
 * 主题队列--消费者
 */
public class Recv1 {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_topic";
    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置主机地址
        factory.setHost("localhost");
        //3.获取连接
        Connection connection = factory.newConnection();
        //4.开启信道
        Channel channel = connection.createChannel();
        //5.绑定交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //6.获取交换机生成的队列名称(排他队列)
        String byNameQueue = channel.queueDeclare().getQueue();
        //7. 将队列和交换机进行绑定同时绑定路由
        String RoutingKey = "*.rabbit.*!";

        channel.queueBind(byNameQueue,EXCHANGE_NAME,RoutingKey); //表示可以当前的消费者可以获取这三个路由下的内容。
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //监听消息队列的回调函数
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        //6.监听通过交换机得到的消息队列
        channel.basicConsume(byNameQueue, true, deliverCallback, consumerTag -> { });
    }
}

生产者:

package topic.send;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

/**
 * 主题队列 ---生产者
 */

public class Send {
    //1.声明交换机名称
    private final static String EXCHANGE_NAME = "exchange_topic";

    public static void main(String[] argv) throws Exception {
        //2.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (
                //3.根据连接工厂获取连接
                Connection connection = factory.newConnection();
                //4.根据连接创建信道
                Channel channel = connection.createChannel()) {
                //5.绑定带交换机                         //Fanout交换机的类型(广播模式)
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
                String infoMessage = "普通信息!";
                String errorMessage = "错误信息!";
                String warningMessage = "警告信息!";
                //路由信息
                String infoRoutingKey = "info.message.orange";
                String errorRoutingKey = "error.rabbit.lazy";
                String warningRoutingKey = "warning.warning.message";

                //发送信息,并且携带路由的key
                channel.basicPublish( EXCHANGE_NAME, infoRoutingKey,null, infoMessage.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish( EXCHANGE_NAME, errorRoutingKey,null, errorMessage.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish( EXCHANGE_NAME, warningRoutingKey,null, warningMessage.getBytes(StandardCharsets.UTF_8));

                System.out.println(" [x] Sent '" + infoMessage + "'");
                System.out.println(" [x] Sent '" + errorMessage + "'");
                System.out.println(" [x] Sent '" + warningMessage + "'");
            }

        }
    }

运行结果:
在这里插入图片描述
可以看到能够根据正则表达式去匹配相应的路由key,这个就是主题模式。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Yjd007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值