模式说明

rabbitmq索引_通配符

Topics模式,也是功能最为强大的一种模式,与routing模式类似,只不过是通过通配符来进行message与queue之间的匹配。

当交换机的模式为topic模式时,根据message的routing key去匹配queue的通配符,以上图为例,Q1的通配符为 *.orange* ,Q2的通配符为 *.*.rabbit lazy.#

* 和 # 都是占位符,* 代表一个单词,# 代表0个或者多个单词,单词直接用 . 分隔。因此Topics模式相对于Routing模式,在匹配上是更加灵活更加强大的。

生产者

交换机类型为 topic

在绑定队列到交换机的时候使用通配符的形式

发送消息时,routing key同样按照通配符的格式传参

package com.leolee.rabbitmq;

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

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @ClassName ProducerPubSub
 * @Description: Topics模式
 * @Author LeoLee
 * @Date 2020/11/6
 * @Version V1.0
 **/
public class ProducerTopics {

    public static void main(String[] args) throws IOException, TimeoutException {

        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //2.设置参数
        connectionFactory.setHost("127.0.0.1");//默认值为localhost
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
        connectionFactory.setUsername("LeoLee");
        connectionFactory.setPassword("lyl512240816");

        //3.创建连接 connection
        Connection connection = connectionFactory.newConnection();

        //4.创建channel
        Channel channel = connection.createChannel();

        //5.创建交换机
        /*
        String exchange:交换机名称
        BuiltinExchangeType type:交换机类型,枚举,
        boolean durable:是否持久化
        boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
        boolean internal:是否内部使用,一般都是false,true代表给MQ内部使用的,比如给MQ开发的插件使用
        Map<String, Object> arguments:相关参数
         */
        String exchangerName = "test_topic";
        channel.exchangeDeclare(exchangerName, BuiltinExchangeType.TOPIC, false, false, false, null);

        //6.创建队列
        /*
         String queue:队列名称
         boolean durable:是否持久化
         boolean exclusive: 有如下两个意义
            是否独占,只有一个消费者监听这个队列
            当connection关闭时,是否删除队列
         boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
         Map<String, Object> arguments: 一些配置参数
         */
        //如果没有一个名字叫xxx的队列,则会创建,如果存在该队列,则复用
        String queueName1 = "test_topic_queue1";
        String queueName2 = "test_topic_queue2";
        channel.queueDeclare(queueName1, false, false, false, null);
        channel.queueDeclare(queueName2, false, false, false, null);

        //7.绑定队列和交换机
        /*
        String queue:队列名称
        String exchange:交换机名称
        String routingkey:路由键,绑定规则
            如果交换机的类型为 fanout,routingkey设置为空值""
            routingkey格式:系统的名称.日志的级别
        */
        channel.queueBind(queueName1, exchangerName, "#.errorLog");

        channel.queueBind(queueName2, exchangerName, "orderSystem.*");
        channel.queueBind(queueName2, exchangerName, "*.*");

        //8.发送消息
        String body1 = "日志信息[error]:又是不想当社畜的一天";
        String body2 = "日志信息[info]:又是不想当社畜的一天";
        String body3 = "日志信息[warning]:又是不想当社畜的一天";
        channel.basicPublish(exchangerName, "orderSysteminfoLog", null, body2.getBytes());//第二个参数routingkey为空
        channel.basicPublish(exchangerName, "web.errorLog", null, body1.getBytes());//第二个参数routingkey为空
        channel.basicPublish(exchangerName, "order.warningLog", null, body3.getBytes());//第二个参数routingkey为空

        //9.释放资源
        channel.close();
        connection.close();

    }

}

运行如下:

rabbitmq索引_rabbitmq_02

rabbitmq索引_rabbitmq索引_03

消费者

消费者代码没有什么特别的,注意代码中routingkey的通配符写法

package com.leolee.rabbitmq;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @ClassName ConsumerPubSub1
 * @Description: Topics模式
 * @Author LeoLee
 * @Date 2020/11/6
 * @Version V1.0
 **/
public class ConsumerTopics1 {

    public static void main(String[] args) throws IOException, TimeoutException {

        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //2.设置参数
        connectionFactory.setHost("127.0.0.1");//默认值为localhost
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
        connectionFactory.setUsername("LeoLee");
        connectionFactory.setPassword("lyl512240816");

        //3.创建连接 connection
        Connection connection = connectionFactory.newConnection();

        //4.创建channel
        Channel channel = connection.createChannel();

        //5.创建队列queue(由于简单模式不需要Exchange,其实是使用默认的交换机,所以消息直接入队列),消费者可以不需要创建队列,但是创建了也不影响
        /*
         String queue:队列名称
         boolean durable:是否持久化
         boolean exclusive: 有如下两个意义
            是否独占,只有一个消费者监听这个队列
            当connection关闭时,是否删除队列
         boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
         Map<String, Object> arguments: 一些配置参数
         */
        //如果没有一个名字叫Hello_world的队列,则会创建,如果存在该队列,则复用
        //生产者已经生命过了队列,可以忽略该步骤
        //channel.queueDeclare("workQueues", false, false, false, null);
        String queueName1 = "test_topic_queue1";

        //6.接收消息
        /*
         * String queue:队列名称
         * boolean autoAck:是否自动确认,当消费者收到消息之后会自动给MQ一个回执,告诉MQ消息已经收到
         * Consumer callback:回调方法
         */
        Consumer consumer = new DefaultConsumer(channel){

            /*
             * 功能描述: <br>
             * 〈回调方法〉当客户端收到消息并向MQ确认消息已经收到,将回调该方法
             * @Param: [consumerTag消息唯一标识,
             *  envelope获取一些信息,包含交换机信息、routing key...等,
             *  properties配置信息,生产者发送消息时候的配置,
             *  body数据]
             * @Return: void
             * @Author: LeoLee
             * @Date: 2020/11/5 11:56
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                /*System.out.println("consumerTag:" + consumerTag);
                System.out.println("envelope.exchange:" + envelope.getExchange());
                System.out.println("envelope.routingKey:" + envelope.getRoutingKey());
                System.out.println("properties:" + properties);*/
                System.out.println("消费者1从队列" + queueName1 + "接收到body:" + new String(body));

            }
        };
        channel.basicConsume(queueName1, true, consumer);

        //7.消费者不需要关闭资源,不然无法完成自动确认
    }
}

分别运行两个消费者,这两个消费者分别绑定了 队列[test_topic_queue1] 和 队列[test_topic_queue2]

rabbitmq索引_java_04

rabbitmq索引_topic_05