RabbitMQ SpringBoot Topic-Exchange模式 应用

一.Topic-Exchange 模式:

模糊匹配,比较Message的routing key和Queue的binding key,按规则匹配成功时,Message才会发送到该Queue。

匹配规则:

  • 第一种: * 匹配单个字母或数字
  • 第二种: # 匹配0~多个字母或数字
    RabbitMQ SpringBoot Topic-Exchange模式 应用_第1张图片

项目使用上一篇中的项目 rabbitmq-produce、rabbitmq-consumer

二.rabbitmq-produce的改动

2.1 在rabbitmq-produce中,新增一个TopicRabbitConfig配置类

TopicRabbitConfig的代码如下:

package com.example.rabbitmqproduce.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Topic-exchange 配置类
 * 模糊匹配,比较Message的routing key和Queue的binding key,按规则匹配成功时,Message才会发送到该Queue
 * 匹配规则:
 * 第一种: * 匹配单个字母或数字
 * 第二种: # 匹配0~多个字母或数字
 */
@Configuration
public class TopicRabbitConfig {

    private Logger logger = LoggerFactory.getLogger(TopicRabbitConfig.class);

    //定义 Topic-exchange模型 的队列名
    private static final String topicQueueNameA = "topicQueueNameA";

    //定义 Topic-exchange模型 的队列名
    private static final String topicQueueNameB = "topicQueueNameB";

    //定义 Topic-exchange模型 的交换机名
    private static final String topicExchangeName = "topicExchange";


    //定义 Topic-exchange模型 的bingingKey
    //他只会接收包含topicQueue.msg的消息
    private static final String topicBindingKeyA = "topicQueue.msg";

    //定义 Topic-exchange模型 的bingingKey
    //他只会接收topicQueue开头的消息
    private static final String topicBindingKeyB = "topicQueue.#";


    /**
     * 队列 起名
     */
    @Bean
    public Queue topiocA() {
        return new Queue(topicQueueNameA);
    }


    @Bean
    public Queue topicB() {
        return new Queue(topicQueueNameB);
    }


    /**
     * Topic交换机 起名:topicExchange
     */
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(topicExchangeName);
    }


    /**
     * 绑定  将队列和交换机绑定
     * @return
     */
    @Bean
    public Binding bindingTopicA() {
        return BindingBuilder.bind(topiocA()).to(topicExchange()).with(topicBindingKeyA);
    }


    /**
     * 绑定  将队列和交换机绑定
     * @return
     */
    @Bean
    public Binding bindingTopicB() {
        return BindingBuilder.bind(topicB()).to(topicExchange()).with(topicBindingKeyB);
    }

}

2.2 新建一个Topic-exchange模式 的消息生产者TopicExchangeProduce类

TopicExchangeProduce 类 的代码如下:

package com.example.rabbitmqproduce.produce;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Topic-exchange模式 的消息生产者
 * @Component 注入到Spring容器中
 */
@Component
public class TopicExchangeProduce {

    //注入一个AmqpTemplate来发布消息
    @Autowired
    private AmqpTemplate rabbitTemplate;

    private Logger logger = LoggerFactory.getLogger(TopicExchangeProduce.class);

    //topic 交换机名称
    private static final String topicExchangeName = "topicExchange";

    //topic 的RoutingKey
    private static final String topicRouteKeyA = "topicQueue.msg";

    //topic 的RoutingKey
    private static final String topicRouteKeyB = "topicQueue.jax.master";

    /**
     * topicA 发送消息
     */
    public void sendMessageTopicA() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "hello!亚索 面对疾风吧";
        String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Map map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        logger.info("发送的内容 : " + map.toString());
        //将消息携带绑定键值:topicQueue.msg 发送到交换机topicExchange
        rabbitTemplate.convertAndSend(topicExchangeName, topicRouteKeyA, map);
    }


    /**
     * topicB 发送消息
     */
    public void sendMessageTopicB() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "hello!贾克斯 我可以打10个";
        String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Map map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        logger.info("发送的内容 : " + map.toString());
        //将消息携带绑定键值:topicQueue.jax.master 发送到交换机topicExchange
        rabbitTemplate.convertAndSend(topicExchangeName, topicRouteKeyB, map);
    }

}

2.3 写个测试的TestController类

代码如下:

package com.example.rabbitmqproduce.controller;

import com.example.rabbitmqproduce.produce.DirectExchangeProduce;
import com.example.rabbitmqproduce.produce.FanoutExchangeProduce;
import com.example.rabbitmqproduce.produce.RabbitMqProduce;
import com.example.rabbitmqproduce.produce.TopicExchangeProduce;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("TestController")
public class TestController {

    private static final Logger logger = LoggerFactory.getLogger(TestController.class);

    @Autowired
    private RabbitMqProduce rabbitMqProduce;

    @Autowired
    private DirectExchangeProduce directExchangeProduce;

    @Autowired
    private FanoutExchangeProduce fanoutExchangeProduce;

    @Autowired
    private TopicExchangeProduce topicExchangeProduce;

    /**
     * 测试基本消息模型(简单队列)
     */
    @RequestMapping(value = "/testSimpleQueue", method = RequestMethod.POST)
    public void testSimpleQueue() {
        logger.info("测试基本消息模型(简单队列)SimpleQueue---开始");
        for (int i = 0; i < 10; i++) {
            rabbitMqProduce.sendMessage();
        }
        logger.info("测试基本消息模型(简单队列)SimpleQueue---结束");
    }


    /**
     * 测试 Direct-exchange模式
     */
    @RequestMapping(value = "/directExchangeTest", method = RequestMethod.POST)
    public void directExchangeTest() {
        logger.info("测试 Direct-exchange模式 队列名为directQueue---开始");
        for (int i = 0; i < 10; i++) {
            directExchangeProduce.sendMessage();
        }
        logger.info("测试 Direct-exchange模式 队列名为directQueue---结束");
    }


    /**
     * 测试 Fanout-exchange模式
     */
    @RequestMapping(value = "/fanoutExchangeTest", method = RequestMethod.POST)
    public void fanoutExchangeTest() {
        logger.info("测试 fanout-exchange模式 队列名为fanoutQueue---开始");
        fanoutExchangeProduce.sendMessage();
        logger.info("测试 fanout-exchange模式 队列名为fanoutQueue---结束");
    }


    /**
     * 测试 Topic-exchange模式   topicA 和 topicB
     */
    @RequestMapping(value = "/topictExchangeTest", method = RequestMethod.POST)
    public void topictExchangeTest() {
        logger.info("测试 topict-exchange模式 队列名为topictQueueNameA---开始");
        topicExchangeProduce.sendMessageTopicA();
        logger.info("测试 topict-exchange模式 队列名为topictQueueNameA---结束");

        logger.info("测试 topict-exchange模式 队列名为topictQueueNameB---开始");
        topicExchangeProduce.sendMessageTopicB();
        logger.info("测试 topict-exchange模式 队列名为topictQueueNameB---结束");
    }
}

三.rabbitmq-consumer的改动

3.1 新建一个Topic-exchange模式 的消息消费者TopicExchangeConsumerA类 和 TopicExchangeConsumerB类

TopicExchangeConsumerA代码如下:

package com.example.rabbitmqconsumer.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;

/**
 * Topic-exchange模式 的消息消费者
 * @RabbitListener(queues = "topicQueueNameA") 监听名为topicQueueNameA的队列
 */

@Component
@RabbitListener(queues = "topicQueueNameA")
public class TopicExchangeConsumerA {

    @Autowired
    private AmqpTemplate rabbitmqTemplate;

    private Logger logger = LoggerFactory.getLogger(TopicExchangeConsumerA.class);

    /**
     * 消费消息
     * @RabbitHandler 代表此方法为接受到消息后的处理方法
     */
    @RabbitHandler
    public void receiveMessage(Map msg){
        logger.info("TopicExchangeA消费者接收到的消息 :" + msg.toString());
    }

}

TopicExchangeConsumerB代码如下:

package com.example.rabbitmqconsumer.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * Topic-exchange模式 的消息消费者
 * @RabbitListener(queues = "topicQueueNameB") 监听名为topicQueueNameB的队列
 */

@Component
@RabbitListener(queues = "topicQueueNameB")
public class TopicExchangeConsumerB {

    @Autowired
    private AmqpTemplate rabbitmqTemplate;

    private Logger logger = LoggerFactory.getLogger(TopicExchangeConsumerB.class);

    /**
     * 消费消息
     * @RabbitHandler 代表此方法为接受到消息后的处理方法
     */
    @RabbitHandler
    public void receiveMessage(Map msg){
        logger.info("TopicExchangeB消费者接收到的消息 :" + msg.toString());
    }

}

四.测试

首先启动生产者rabbitmq-produce项目。在postman或浏览器上访问:
http://localhost:8783/TestController/topictExchangeTest POST请求
这时可以在rabbitmq-produce的控制台可以看到
RabbitMQ SpringBoot Topic-Exchange模式 应用_第2张图片
然后再启动消费者rabbitmq-consumer工程,在rabbitmq-consumer可以看到:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200226180254338.png)可以看到 绑定了这个交换机的所有队列都收到生产者发送的消息 。

你可能感兴趣的:(SpringBoot,Rabbit,MQ)