Rabbit工作模式之路由模式

    本文根据视频https://www.bilibili.com/video/BV1pa4y1x7Kc?p=9和https://www.bilibili.com/video/BV1pa4y1x7Kc?p=10创作。未经视频作者授权,如果作者感到侵权,请联系本人删除此文

         路由模式结构图如下:

         Rabbit工作模式之路由模式_第1张图片

        路由模式特点如下:

               1.  一个交换机绑定多个队列,每个队列设置routingkey,一个队列可以设置多个routingkey

               2. 每个消费者监听自己的队列

               3. 生产者将消息发送给交换机,需要指定routingkey的值,交换机再转发给相同routingkey的队列

        路由模式生产者代码:

        

public class RoutingProducer {

    private static final String QUEUE_EMAIL = "queue_email";

    private static final String QUEUE_SMS = "queue_sms";

    private static final String EXCHANGE_ROUTING = "exchange_rounting";

    private static final String EMAIL_ROUTING_KEY = "email_key";

    private static final String SMS_ROUTING_KEY = "sms_key";

    private static final String ALL_ROUTING_KEY = "all_key";

    public static void main(String[] args) {
        //通过连接工厂创建新的连接和MQ建立连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        //设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null;
        Channel channel = null;
        try {
            //建立新的连接
            connection = connectionFactory.newConnection();
            //创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
            channel = connection.createChannel();
            //声明队列,如果队列在MQ中不存在则创建
            channel.queueDeclare(QUEUE_SMS, true, false, false,null);
            channel.queueDeclare(QUEUE_EMAIL, true, false, false,null);
            //声明交换机
            //参数: String exchange, String type
            /**
             * 参数明细
             * 1. exchange 交换机名称
             * 2. 交换机类型
             * fanout: 对应发布订阅模式
             * direct: 对应路由模式
             * topic: 对应通配符模式
             * headers: 对应header转发模式
             */
            channel.exchangeDeclare(EXCHANGE_ROUTING, BuiltinExchangeType.DIRECT);
            //绑定交换机和队列
            //参数: String queue, String exchange, String routingKey
            /**
             * 参数明细:
             * 1. queue 队列名称
             * 2. exchange 交换机名称
             * 3. routingKey 路由key,作用是交换机会根据路由key的值转发到指定的队列,在发布订阅模式为空串
             */
            channel.queueBind(QUEUE_EMAIL, EXCHANGE_ROUTING, EMAIL_ROUTING_KEY);
            //绑定多个队列
            channel.queueBind(QUEUE_EMAIL, EXCHANGE_ROUTING, ALL_ROUTING_KEY);

            channel.queueBind(QUEUE_SMS, EXCHANGE_ROUTING, SMS_ROUTING_KEY);
            //绑定多个队列
            channel.queueBind(QUEUE_SMS, EXCHANGE_ROUTING, ALL_ROUTING_KEY);
            //发送消息制定rounting key
            String message = "Hello World email";
            String message1 = "Hello World sms";
            String message2 = "Hello World all";
            channel.basicPublish(EXCHANGE_ROUTING, EMAIL_ROUTING_KEY, null, message.getBytes());
            channel.basicPublish(EXCHANGE_ROUTING, SMS_ROUTING_KEY, null, message1.getBytes());
            channel.basicPublish(EXCHANGE_ROUTING, ALL_ROUTING_KEY, null, message2.getBytes());
            System.out.println("send to mq " + message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭连接
            //先关闭通道,在关闭连接
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
            try {
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者email代码:

public class RoutingConsumerEmail {

    private static final String QUEUE_EMAIL = "queue_email";

    private static final String EXCHANGE_ROUTING = "exchange_rounting";

    private static final String EMAIL_ROUTING_KEY = "email_key";

    public static void main(String[] args) throws IOException, TimeoutException {
        //通过连接工厂创建新的连接和MQ建立连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        //设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null;
        Channel channel = null;
        //建立新的连接
        connection = connectionFactory.newConnection();
        //创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
        channel = connection.createChannel();
        //声明队列,如果队列在MQ中不存在则创建
        channel.queueDeclare(QUEUE_EMAIL, true, false, false, null);
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_ROUTING, BuiltinExchangeType.DIRECT);
        //绑定交换机和队列
        channel.queueBind(QUEUE_EMAIL, EXCHANGE_ROUTING, EMAIL_ROUTING_KEY);

        //实现消费方法
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("receive message: " + message);
            }
        };

        //监听队列
        channel.basicConsume(QUEUE_EMAIL, true, defaultConsumer);
    }
}

消费者SMS代码:

public class RoutingConsumerSms {

    private static final String QUEUE_SMS = "queue_sms";

    private static final String EXCHANGE_ROUTING = "exchange_rounting";

    private static final String SMS_ROUTING_KEY = "sms_key";

    public static void main(String[] args) throws IOException, TimeoutException {
        //通过连接工厂创建新的连接和MQ建立连接
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        //设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null;
        Channel channel = null;
        //建立新的连接
        connection = connectionFactory.newConnection();
        //创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
        channel = connection.createChannel();
        //声明队列,如果队列在MQ中不存在则创建
        channel.queueDeclare(QUEUE_SMS, true, false, false, null);
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_ROUTING, BuiltinExchangeType.DIRECT);
        //绑定交换机和队列
        channel.queueBind(QUEUE_SMS, EXCHANGE_ROUTING, SMS_ROUTING_KEY);

        //实现消费方法
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("receive message: " + message);
            }
        };

        //监听队列
        channel.basicConsume(QUEUE_SMS, true, defaultConsumer);
    }
}

关于代码验证结果有个疑问:

       消费者没有绑定ALL_KEY这个路由key,但是可以接收到这个路由key的消息。如果启动了https://blog.csdn.net/wqc8994/article/details/106893121中的发布订阅模式的消费者,则all_key的信息不被路由消费者接收,而是被订阅消费者接收。目前个人不知道为啥,待以后有更深了解解决。如有知道的大佬也请评论告知。

你可能感兴趣的:(RabbitMQ)