6、Spring Boot 3.x集成RabbitMQ动态交换机、队列

一、前言

复制代码
本篇主要是围绕着 Spring Boot 3.x 与 RabbitMQ 的动态配置集成,比如动态新增 RabbitMQ 交换机、队列等操作。

二、默认RabbitMQ中的exchange、queue动态新增及监听

1、新增RabbitMQ配置

RabbitMQConfig.java
java 复制代码
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @className: RabbitConfig
 * @program: chain
 * @description: RabbitMQ 配置类
 * @author: kenny
 * @create: 2024-10-03 21:59
 * @version: 1.0.0
 */
@Configuration
@EnableRabbit
public class RabbitMQConfig {

    /**
     * 创建 RabbitTemplate, 用于发送消息
     *
     * @return RabbitTemplate
     */
    @Bean
    public RabbitTemplate rabbitTemplate() {
        return new RabbitTemplate();
    }

    /**
     * 创建 RabbitAdmin, 用于创建 Exchange 和 Queue
     *
     * @param rabbitTemplate RabbitTemplate
     * @return RabbitAdmin
     */
    @Bean
    public RabbitAdmin rabbitAdmin(RabbitTemplate rabbitTemplate) {
        return new RabbitAdmin(rabbitTemplate);
    }
}

2、新增RabbitMQ动态操作组件

RabbitDynamicConfigService.java
复制代码
RabbitDynamicConfigService.java 中包含了不同类型Exchange的创建、删除,Queue的创建和删除、绑定Exchange
java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @className: RabbitDynamicConfigService
 * @program: chain
 * @description: 动态创建队列和交换机
 * @author: kenny
 * @create: 2024-10-03 23:49
 * @version: 1.0.0
 */
@Slf4j
@Service
public class RabbitDynamicConfigService {

    /**
     * 为了解决循环依赖问题
     */
    private final RabbitAdmin rabbitAdmin;
    private final RabbitListenerService rabbitListenerService;

    @Autowired
    public RabbitDynamicConfigService(RabbitAdmin rabbitAdmin,
                                      RabbitListenerService rabbitListenerService) {
        this.rabbitAdmin = rabbitAdmin;
        this.rabbitListenerService = rabbitListenerService;
    }

    /**
     * 动态创建队列,并持久化
     *
     * @param queueName 队列名称
     */
    public void createQueue(String queueName) {
        // 队列持久化
        Queue queue = new Queue(queueName, true);
        // 创建队列
        rabbitAdmin.declareQueue(queue);
        System.out.println("队列创建成功: " + queueName);
    }

    /**
     * 动态创建队列,并持久化
     *
     * @param queueName 队列名称
     */
    public void createQueue(String queueName, Boolean isListener) {
        // 队列持久化
        Queue queue = new Queue(queueName, true);
        // 创建队列
        rabbitAdmin.declareQueue(queue);
        System.out.println("队列创建成功: " + queueName);

        if (!isListener) {
            return;
        }

        rabbitListenerService.createListener(queueName);
    }


    /**
     * 动态创建交换机,并持久化
     *
     * @param exchangeName 交换机名称
     */
    public void createExchange(String exchangeName) {
        // 交换机持久化
        DirectExchange exchange = new DirectExchange(exchangeName, true, false);
        rabbitAdmin.declareExchange(exchange);
        log.info("交换机创建成功: {}", exchangeName);
    }


    // 动态创建 Fanout 交换机
    public void createDirectExchange(String exchangeName) {
        DirectExchange fanoutExchange = new DirectExchange(exchangeName, true, false); // 持久化
        rabbitAdmin.declareExchange(fanoutExchange);
        log.info("Direct 交换机创建成功: {}", exchangeName);
    }

    // 动态创建 Fanout 交换机
    public void createFanoutExchange(String exchangeName) {
        FanoutExchange fanoutExchange = new FanoutExchange(exchangeName, true, false); // 持久化
        rabbitAdmin.declareExchange(fanoutExchange);
        log.info("Fanout 交换机创建成功: {}", exchangeName);
    }

    // 动态创建 Topic 交换机
    public void createTopicExchange(String exchangeName) {
        TopicExchange topicExchange = new TopicExchange(exchangeName, true, false); // 持久化
        rabbitAdmin.declareExchange(topicExchange);
        log.info("Topic 交换机创建成功: {}", exchangeName);
    }

    // 动态创建 Headers 交换机
    public void createHeadersExchange(String exchangeName) {
        HeadersExchange headersExchange = new HeadersExchange(exchangeName, true, false); // 持久化
        rabbitAdmin.declareExchange(headersExchange);
        log.info("Headers 交换机创建成功: {}", exchangeName);
    }

    /**
     * 动态绑定队列到交换机,并指定路由键
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     */
    public void bindQueueToExchange(String queueName, String exchangeName, String routingKey) {
        Queue queue = new Queue(queueName);
        DirectExchange exchange = new DirectExchange(exchangeName);
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);
        rabbitAdmin.declareBinding(binding);
        log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);
    }

    /**
     * 动态绑定队列到交换机,并指定路由键
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     */
    public void moreExchangeTypeBindQueueToExchange(String queueName, String exchangeType, String exchangeName, String routingKey, Map<String, Object> headers) {
        switch (exchangeType) {
            case "fanout" -> bindQueueToExchange(queueName, exchangeName, routingKey);
            case "direct" -> bindQueueToDirectExchange(queueName, exchangeName, routingKey);
            case "topic" -> bindQueueToTopicExchange(queueName, exchangeName, routingKey);
            case "headers" -> bindQueueToHeadersExchange(queueName, exchangeName, headers);
            default -> throw new IllegalArgumentException("不支持的交换机类型: " + exchangeType);
        }
    }

    /**
     * 动态绑定队列到交换机,并指定路由键(exchange: direct)
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     */
    public void bindQueueToFanoutExchange(String queueName, String exchangeName) {
        Queue queue = new Queue(queueName);
        FanoutExchange exchange = new FanoutExchange(exchangeName);
        Binding binding = BindingBuilder.bind(queue).to(exchange);
        rabbitAdmin.declareBinding(binding);
        log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName);
    }

    /**
     * 动态绑定队列到交换机,并指定路由键(exchange: direct)
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     */
    public void bindQueueToDirectExchange(String queueName, String exchangeName, String routingKey) {
        Queue queue = new Queue(queueName);
        DirectExchange exchange = new DirectExchange(exchangeName);
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);
        rabbitAdmin.declareBinding(binding);
        log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);
    }

    /**
     * 动态绑定队列到交换机,并指定路由键(exchange: topic)
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     */
    public void bindQueueToTopicExchange(String queueName, String exchangeName, String routingKey) {
        Queue queue = new Queue(queueName);
        TopicExchange exchange = new TopicExchange(exchangeName);
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);
        rabbitAdmin.declareBinding(binding);
        log.info("绑定创建成功: {}", queueName + " -> {}", exchangeName + " 使用路由键: {}", routingKey);
    }

    /**
     * 动态绑定队列到交换机,并指定路由键(exchange: headers)
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param headers      路由键
     */
    public void bindQueueToHeadersExchange(String queueName, String exchangeName, Map<String, Object> headers) {
        Queue queue = new Queue(queueName);
        HeadersExchange exchange = new HeadersExchange(exchangeName);
        Binding binding = BindingBuilder.bind(queue).to(exchange).whereAll(headers).match();
        rabbitAdmin.declareBinding(binding);
        log.info("队列 {}", queueName + " 已绑定到 Headers 交换机 {}", exchangeName + ",使用头部匹配规则: {}", headers);
    }

    /**
     * 动态删除队列
     *
     * @param queueName 队列名称
     */
    public void deleteQueue(String queueName) {
        rabbitAdmin.deleteQueue(queueName);
        log.info("队列删除成功: {}", queueName);
    }

    /**
     * 动态删除交换机
     *
     * @param exchangeName 交换机名称
     */
    public void deleteExchange(String exchangeName) {
        rabbitAdmin.deleteExchange(exchangeName);
        log.info("交换机删除成功: {}", exchangeName);
    }
}

3、RabbitMQ中队列的动态监听

RabbitListenerService.java
java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @className: RabbitListenerService
 * @program: chain
 * @description: RabbitMQ监听器Service组件
 * @author: kenny
 * @create: 2024-10-04 01:40
 * @version: 1.0.0
 */
@Slf4j
@Service
public class RabbitListenerService {

    // 为了解决循环依赖问题
    private final SimpleRabbitListenerContainerFactory listenerContainerFactory;
    private final ConnectionFactory connectionFactory;

    @Autowired
    public RabbitListenerService(
            SimpleRabbitListenerContainerFactory listenerContainerFactory,
            ConnectionFactory connectionFactory) {
        this.listenerContainerFactory = listenerContainerFactory;
        this.connectionFactory = connectionFactory;
    }

    /**
     * 创建监听器容器并启动监听
     *
     * @param queueName 队列名称
     */
    public void createListener(String queueName) {
        // 创建并启动监听器容器
        SimpleMessageListenerContainer container = listenerContainerFactory.createListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(queueName);

        // 监听逻辑处理
        container.setMessageListener(new MessageListenerAdapter(new Object() {
            public void handleMessage(String message) {
                System.out.println("收到来自RabbitMQ中队列:" + queueName + " 队列的消息:" + message);
            }
        }));

        // 启动监听器容器
        container.start();
        System.out.println("RabbitMQ队列监听器已启动:" + queueName);
    }
}

4、RabbitMQ中的Exchange、Queue动态操作接口

RabbitDynamicChannelController.java
java 复制代码
import com.chain.air.rpp.exchange.rabbit.RabbitDynamicConfigService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @className: RabbitDynamicController
 * @program: chain
 * @description: RabbitMQ 动态创建队列、交换机,绑定等操作
 * @author: kenny
 * @create: 2024-10-04 00:22
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/rabbit/dynamic/channel")
public class RabbitDynamicChannelController {

    /**
     * 动态创建队列和交换机
     */
    @Resource
    private RabbitDynamicConfigService rabbitDynamicConfigService;

    /**
     * 动态创建队列
     *
     * @param queueName 队列名称
     * @return 处理结果
     */
    @GetMapping("/createQueue")
    public String createQueue(@RequestParam("queueName") String queueName) {
        rabbitDynamicConfigService.createQueue(queueName);
        return "队列已创建: " + queueName;
    }

    /**
     * 动态创建交换机
     *
     * @param exchangeName 交换机名称
     * @return 处理结果
     */
    @GetMapping("/createExchange")
    public String createExchange(@RequestParam("exchangeName") String exchangeName) {
        rabbitDynamicConfigService.createExchange(exchangeName);
        return "交换机已创建: " + exchangeName;
    }

    /**
     * 动态绑定队列和交换机
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由键
     * @return 处理结果
     */
    @GetMapping("/bindQueue")
    public String bindQueueToExchange(@RequestParam("queueName") String queueName,
                                      @RequestParam("exchangeName") String exchangeName,
                                      @RequestParam("routingKey") String routingKey) {
        rabbitDynamicConfigService.bindQueueToExchange(queueName, exchangeName, routingKey);
        return "队列和交换机已绑定: " + queueName + " -> " + exchangeName;
    }

    /**
     * 动态删除队列
     *
     * @param queueName 队列名称
     * @return 处理结果
     */
    @GetMapping("/deleteQueue")
    public String deleteQueue(@RequestParam("queueName") String queueName) {
        rabbitDynamicConfigService.deleteQueue(queueName);
        return "队列已删除: " + queueName;
    }

    /**
     * 动态删除交换机
     *
     * @param exchangeName 交换机名称
     * @return 处理结果
     */
    @GetMapping("/deleteExchange")
    public String deleteExchange(@RequestParam("exchangeName") String exchangeName) {
        rabbitDynamicConfigService.deleteExchange(exchangeName);
        return "交换机已删除: " + exchangeName;
    }

    // 创建并绑定 Fanout 交换机
    @GetMapping("/createDirectExchange")
    public String createDirectExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam String routingKey) {
        rabbitDynamicConfigService.createDirectExchange(exchangeName);
        rabbitDynamicConfigService.bindQueueToDirectExchange(queueName, exchangeName, routingKey);
        return "Fanout Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with routing key: " + routingKey;
    }

    // 创建并绑定 Fanout 交换机
    @GetMapping("/createFanoutExchange")
    public String createFanoutExchange(@RequestParam String exchangeName, @RequestParam String queueName) {
        rabbitDynamicConfigService.createFanoutExchange(exchangeName);
        rabbitDynamicConfigService.bindQueueToFanoutExchange(queueName, exchangeName);
        return "Fanout Exchange and Queue Binding created: " + exchangeName + " -> " + queueName;
    }

    // 创建并绑定 Topic 交换机
    @GetMapping("/createTopicExchange")
    public String createTopicExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam String routingKey) {
        rabbitDynamicConfigService.createTopicExchange(exchangeName);
        rabbitDynamicConfigService.bindQueueToTopicExchange(queueName, exchangeName, routingKey);
        return "Topic Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with routing key: " + routingKey;
    }

    // 创建并绑定 Headers 交换机
    @GetMapping("/createHeadersExchange")
    public String createHeadersExchange(@RequestParam String exchangeName, @RequestParam String queueName, @RequestParam Map<String, String> headersMap) {
        Map<String, Object> headers = new HashMap<>(headersMap);
        rabbitDynamicConfigService.createHeadersExchange(exchangeName);
        rabbitDynamicConfigService.bindQueueToHeadersExchange(queueName, exchangeName, headers);
        return "Headers Exchange and Queue Binding created: " + exchangeName + " -> " + queueName + " with headers: " + headers;
    }
}

5、RabbitMQ中的Queue消息监听动态操作接口

RabbitChannelListenerController.java
java 复制代码
import com.chain.air.rpp.exchange.rabbit.RabbitDynamicConfigService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @className: RabbitListenerController
 * @program: chain
 * @description: RabbitMQ 监听器 Controller 组件
 * @author: kenny
 * @create: 2024-10-04 01:30
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/rabbit/channel/listener")
public class RabbitChannelListenerController {

    @Resource
    private RabbitDynamicConfigService rabbitDynamicConfigService;

    /**
     * 创建监听器,监听指定队列
     *
     * @param queueName 队列名称
     * @return 处理结果
     */
    @GetMapping("/queue")
    public String listenQueue(@RequestParam("queueName") String queueName) {
        rabbitDynamicConfigService.createQueue(queueName, true);
        return "开始监听队列:" + queueName;
    }
}

三、动态exchange、queue的测试

1、测试Exchange、Queue的动态创建和删除

2、测试Exchange和Queue的动态绑定

3、发送、接收消息测试动态创建Exchange、Queue

4、测试Queue的动态监听接口

下一篇:7、Spring Boot 3.x集成RabbitMQ动态实例等操作

相关推荐
dkbnull14 小时前
深入理解Spring两大特性:IoC和AOP
spring boot
初次攀爬者14 小时前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
洋洋技术笔记19 小时前
Spring Boot条件注解详解
java·spring boot
洋洋技术笔记2 天前
Spring Boot配置管理最佳实践
spring boot
用户8307196840823 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
大道至简Edward3 天前
Spring Boot 2.7 + JDK 8 升级到 Spring Boot 3.x + JDK 17 完整指南
spring boot·后端
洋洋技术笔记3 天前
Spring Boot启动流程解析
spring boot·后端
怒放吧德德3 天前
Spring Boot 实战:RSA+AES 接口全链路加解密(防篡改 / 防重放)
java·spring boot·后端
李慕婉学姐3 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
QQ5110082853 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php