SpringBoot整合RabbitMQ之Topic主题交换器

RabbitMQ中的Topic主题交换器:

Topic交换器是主题模式,通过模式匹配分发消息的路由键属性,将路由键和某种模式进行匹配,此时队列需要绑定一种模式,Topic交换器将路由键和绑定的字符串切分成单词,这些单词直接用点“.”隔开。该交换器会识别两个通配符:“#”和“*”,其中“#”匹配0个或多个单词,“*”匹配不多不少一个单词。

 

以下案例为实现Topic主题交换器的过程,本案例在上一章的基础之上编写的,需要这两个项目:rabbitmq-provider (生产者),一个rabbitmq-consumer(消费者)。

首先在rabbitmq-provider项目上创建 TopicRabbitConfig配置类

package com.rabbitmq.provider.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class TopicRabbitConfig {

    // 绑定键
    private final String man = "topic.man";
    private final String woman = "topic.women";

    @Bean
    Queue firstQueue() {
        return new Queue(man);
    }

    @Bean
    Queue secondQueue() {
        return new Queue(woman);
    }

    @Bean
    TopicExchange exchange(){
        return new TopicExchange("topicExchange");
    }

    //将firstQueue和topicExchange绑定,而且绑定的键值为topic.man
    //这样只要是消息携带的路由键是topic.man,才会分发到该队列
    @Bean
    Binding bindingExchangeMessage(){
        return BindingBuilder.bind(firstQueue()).to(exchange()).with(man);
    }

    //将secondQueue和topicExchange绑定,而且绑定的键值为用上通配路由键规则topic.#
    // 这样只要是消息携带的路由键是以topic.开头,都会分发到该队列
    @Bean
    Binding bindingExchangeMessage2(){
        return BindingBuilder.bind(secondQueue()).to(exchange()).with("topic.#");
    }
}

然后在Controller里面多加两个接口

    @GetMapping("/sendTopicMessage1")
    public String sendTopicMessage1() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: M A N ";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> manMap = new HashMap<>();
        manMap.put("messageId", messageId);
        manMap.put("messageData", messageData);
        manMap.put("createTime", createTime);
        rabbitTemplate.convertAndSend("topicExchange", "topic.man", manMap);
        return "ok";
    }

    @GetMapping("/sendTopicMessage2")
    public String sendTopicMessage2() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: woman is all ";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> womanMap = new HashMap<>();
        womanMap.put("messageId", messageId);
        womanMap.put("messageData", messageData);
        womanMap.put("createTime", createTime);
        rabbitTemplate.convertAndSend("topicExchange", "topic.woman", womanMap);
        return "ok";
    }

生产者这边的操作已经完成,接下来去rabbitmq-consumer项目上编写后续代码

创建TopicManReceiver

package com.rabbitmq.consumer.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;


@Component
@RabbitListener(queues = "topic.man")
public class TopicManReceiver {

    @RabbitHandler
    public void process(Map message){
        System.out.println("TopicManReceiver消费者收到消息 = " + message.toString());
    }
}

创建TopicWoManReceiver

package com.rabbitmq.consumer.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;


@Component
@RabbitListener(queues = "topic.woman")
public class TopicWoManReceiver {

    @RabbitHandler
    public void process(Map message) {
        System.out.println("TopicWoManReceiver消费者收到消息 = " + message);
    }
}

创建TopicRabbitConfig配置类

package com.rabbitmq.consumer.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicRabbitConfig {
    //绑定键
    public final static String man = "topic.man";
    public final static String woman = "topic.woman";

    @Bean
    public Queue firstQueue() {
        return new Queue(TopicRabbitConfig.man);
    }

    @Bean
    public Queue secondQueue() {
        return new Queue(TopicRabbitConfig.woman);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange("topicExchange");
    }


    //将firstQueue和topicExchange绑定,而且绑定的键值为topic.man
    //这样只要是消息携带的路由键是topic.man,才会分发到该队列
    @Bean
    Binding bindingExchangeMessage() {
        return BindingBuilder.bind(firstQueue()).to(exchange()).with(man);
    }

    //将secondQueue和topicExchange绑定,而且绑定的键值为用上通配路由键规则topic.#
    // 这样只要是消息携带的路由键是以topic.开头,都会分发到该队列
    @Bean
    Binding bindingExchangeMessage2() {
        return BindingBuilder.bind(secondQueue()).to(exchange()).with("topic.#");
    }

}

然后把这两个项目跑起来,使用postman工具调用/sendTopicMessage1接口

 

再调用/sendTopicMessage2接口

 

 

 可以看到,sendTopicMessage1调用的时候

man和woman都消费到了信息,因为它们使用的是主题交换机,而woman绑定的路由是topic.#,“#”匹配0个或多个单词,所以woman能消费到这个接口的信息

当调用sendTopicMessage2的时候,

man消费不到woman的信息,因为man的路由是topic.man,只能消费topic.man的信息。

 

posted @ 2021-04-15 13:23  过期可乐  阅读(279)  评论(0编辑  收藏  举报