Spring Boot 集成 RabbitMQ 自动创建交换机、队列并绑定

在使用 Spring Boot 开发消息队列应用时,我们经常需要在应用启动时自动创建 RabbitMQ 的交换机、队列和绑定关系。 

一、添加依赖

在 Spring Boot 项目中使用 RabbitMQ,首先需要添加 RabbitMQ 的依赖。在 pom.xml 文件中添加以下依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

二、配置 RabbitMQ

在 Spring Boot 的配置文件 application.yml 中,配置 RabbitMQ 的连接信息

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest

 三、代码

使用 @Configuration注解

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 RabbitMQConfig {

    @Bean
    public Queue myQueue() {
        return new Queue("myQueue", true);
    }

    @Bean
    public TopicExchange myExchange() {
        return new TopicExchange("myExchange");
    }

    @Bean
    public Binding binding() {
        return BindingBuilder.bind(myQueue()).to(myExchange()).with("routingKey");
    }
}

使用 @PostConstruct 注解

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.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class RabbitMQConfig {

    @Autowired
    private ConnectionFactory connectionFactory;

    @PostConstruct
    public void init() {
        RabbitAdmin admin = new RabbitAdmin(connectionFactory);
        // 定义交换机
        DirectExchange directExchange = new DirectExchange("directExchange");
        admin.declareExchange(directExchange);
        // 定义队列
        Queue myQueue = new Queue("myQueue");
        admin.declareQueue(myQueue);
        // 定义绑定关系
        admin.declareBinding(BindingBuilder.bind(myQueue).to(directExchange).with("routingKey"));
    }

}

 实现 ApplicationListener 接口


import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class RabbitMQApplicationListener implements ApplicationListener<ContextRefreshedEvent> {


    @Autowired
    private ConnectionFactory connectionFactory;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        RabbitAdmin admin = new RabbitAdmin(connectionFactory);
        // 定义交换机 广播模式
        FanoutExchange fanoutExchange = new FanoutExchange("fanoutExchange");
        admin.declareExchange(fanoutExchange);
        // 定义队列
        Queue myQueue1 = new Queue("myQueue1");
        admin.declareQueue(myQueue1);
        // 定义队列
        Queue myQueue2 = new Queue("myQueue2");
        admin.declareQueue(myQueue2);
        // 定义绑定关系
        admin.declareBinding(BindingBuilder.bind(myQueue1).to(fanoutExchange));
        admin.declareBinding(BindingBuilder.bind(myQueue2).to(fanoutExchange));
    }
}

<think> 我们使用Spring Boot集成RabbitMQ时,消费者端通常使用`@RabbitListener`注解来监听队列。但有时我们需要在消费者中获取交换机(Exchange)队列(Queue)的信息,例如进行动态绑定等操作。 在Spring AMQP中,我们可以通过`AmqpAdmin`接口来获取管理交换机队列以及绑定关系。另外,我们也可以通过声明Bean的方式来创建交换机队列,然后注入这些Bean到消费者中使用。 下面我将给出两种方式: 1. 通过`AmqpAdmin`获取交换机队列。 2. 在配置类中声明交换机队列的Bean,然后在消费者中注入。 注意:这里假设已经完成了RabbitMQ的基本配置(如连接信息等)。 方式一:使用AmqpAdmin 我们可以在需要的地方注入`AmqpAdmin`,然后调用其方法来获取交换机队列的信息。 方式二:声明Bean注入 在配置类中声明交换机队列的Bean,这样它们就会被自动创建(如果RabbitMQ中不存在),然后我们可以在消费者中注入这些Bean。 接下来,我将分别给出示例代码。 首先,确保在Spring Boot项目中已经引入了相关依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> <version>2.7.18</version> </dependency> ``` 方式一:使用AmqpAdmin获取交换机队列 注意:`AmqpAdmin`的`getQueueProperties`方法可以获取队列的属性,但是获取交换机目前没有直接的方法。通常,我们通过声明Bean的方式获取交换机对象。 示例代码(获取队列属性): ```java import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class QueueInfoService { @Autowired private AmqpAdmin amqpAdmin; public void printQueueInfo(String queueName) { // 获取队列的属性 Queue queue = QueueBuilder.durable(queueName).build(); // 注意:getQueueProperties方法返回的是队列的属性,如消息数、消费者数等 Properties properties = amqpAdmin.getQueueProperties(queueName); if (properties != null) { System.out.println("Queue: " + queueName); System.out.println("Message count: " + properties.get("QUEUE_MESSAGE_COUNT")); System.out.println("Consumer count: " + properties.get("QUEUE_CONSUMER_COUNT")); } else { System.out.println("Queue not found: " + queueName); } } } ``` 但是,对于交换机,`AmqpAdmin`没有直接提供获取交换机的方法。因此,如果我们需要交换机的信息,通常采用方式二。 方式二:在配置类中声明Bean,然后注入 配置类中声明交换机队列: ```java import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { // 定义交换机 @Bean public DirectExchange myDirectExchange() { return new DirectExchange("my.direct.exchange", true, false); } // 定义队列 @Bean public Queue myQueue() { return new Queue("my.queue", true); } // 绑定 @Bean public Binding binding() { return BindingBuilder.bind(myQueue()).to(myDirectExchange()).with("my.routing.key"); } } ``` 然后在消费者中注入这些Bean: ```java import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.Queue; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MyConsumer { private final DirectExchange directExchange; private final Queue queue; @Autowired public MyConsumer(DirectExchange myDirectExchange, Queue myQueue) { this.directExchange = myDirectExchange; this.queue = myQueue; } // 使用@RabbitListener监听队列 @RabbitListener(queues = "my.queue") public void handleMessage(String message) { System.out.println("Received message: " + message); // 这里可以使用注入的exchangequeue System.out.println("Exchange name: " + directExchange.getName()); System.out.println("Queue name: " + queue.getName()); } } ``` 这样,我们就可以在消费者中获取到交换机队列的信息。 注意事项: 1. 如果交换机队列已经在RabbitMQ中存在,我们也可以直接通过名称来使用,但是通过声明Bean的方式可以确保它们存在,且可以在代码中直接引用。 2. 使用`AmqpAdmin`可以动态创建删除交换机队列,也可以获取队列的属性(如消息数量等),但是无法获取交换机的属性(交换机的属性在Spring AMQP中没有提供获取方法)。 总结: 对于队列,我们可以通过`AmqpAdmin`的`getQueueProperties`方法获取其属性(注意:不是队列对象,而是属性)。对于交换机,如果我们需要在代码中引用,最好在配置类中声明为Bean,然后注入使用。 因此,根据不同的需求选择不同的方式。 相关问题: §§相关问题§§: 1. 如何在Spring Boot中动态创建一个RabbitMQ队列? 2. 如何使用`AmqpAdmin`删除一个交换机? 3. 在RabbitMQ中,如何获取一个队列中的消息数量? 4. 如何在消费者中动态绑定队列交换机? </think> 在Spring Boot集成RabbitMQ时,消费者获取交换机队列主要通过声明式配置实现。以下是详细实现方式代码示例: ### 方法一:配置类声明交换机队列(推荐) ```java import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { // 声明直连交换机 @Bean public DirectExchange orderExchange() { return new DirectExchange("order.direct", true, false); // 持久化,不自动删除 } // 声明队列 @Bean public Queue orderQueue() { return new Queue("order.queue", true, false, false); // 参数:持久化,非独占,不自动删除 } // 绑定队列交换机 @Bean public Binding orderBinding() { return BindingBuilder.bind(orderQueue()) .to(orderExchange()) .with("order.routingKey"); } // 声明死信交换机 @Bean public TopicExchange orderDlxExchange() { return new TopicExchange("order.dlx", true, false); } // 声明死信队列 @Bean public Queue orderDlxQueue() { return QueueBuilder.durable("order.dlx.queue") .withArgument("x-message-ttl", 60000) // 消息TTL .build(); } // 绑定死信队列 @Bean public Binding dlxBinding() { return BindingBuilder.bind(orderDlxQueue()) .to(orderDlxExchange()) .with("order.dlx.#"); } } ``` ### 方法二:在消费者中动态声明 ```java import org.springframework.amqp.core.*; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class OrderConsumer { @Autowired private AmqpAdmin amqpAdmin; @RabbitListener(queues = "order.queue") public void processOrder(Order order) { // 动态创建备用队列 Queue backupQueue = new Queue("order.backup", true); amqpAdmin.declareQueue(backupQueue); // 动态创建备用交换机 DirectExchange backupExchange = new DirectExchange("order.backup", true, false); amqpAdmin.declareExchange(backupExchange); // 动态绑定 Binding binding = BindingBuilder.bind(backupQueue) .to(backupExchange) .with("backup.routingKey"); amqpAdmin.declareBinding(binding); // 业务处理逻辑... } } ``` ### 方法三:使用注解声明队列绑定 ```java import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class PaymentConsumer { // 注解方式声明队列/交换机/绑定 @RabbitListener(bindings = @QueueBinding( value = @Queue(name = "payment.queue", durable = "true"), exchange = @Exchange(name = "payment.direct", type = "direct"), key = "payment.routingKey" )) public void handlePayment(Payment payment) { // 消费者逻辑 System.out.println("处理支付: " + payment.getId()); } } ``` ### 获取已声明的交换机队列信息 ```java import org.springframework.amqp.core.AmqpAdmin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class RabbitInfoService { @Autowired private AmqpAdmin amqpAdmin; // 获取队列属性 public void getQueueInfo(String queueName) { Properties properties = amqpAdmin.getQueueProperties(queueName); if (properties != null) { System.out.println("队列消息数: " + properties.get("QUEUE_MESSAGE_COUNT")); System.out.println("消费者数量: " + properties.get("QUEUE_CONSUMER_COUNT")); } } // 检查交换机是否存在 public boolean exchangeExists(String exchangeName) { return amqpAdmin.getExchangeInfo(exchangeName) != null; } } ``` ### 关点解释: 1. **声明方式选择**: - 配置类声明:适合固定基础设施 - 注解声明:简洁但灵活性有限 - 动态声明:适合运行时创建资源 2. **队列参数**: ```java QueueBuilder.durable("queueName") .withArgument("x-dead-letter-exchange", "dlx.exchange") // 死信交换机 .withArgument("x-message-ttl", 60000) // 消息TTL .withArgument("x-max-length", 1000) // 最大消息数 .build(); ``` 3. **交换机类型**: - `DirectExchange`:精确路由 - `TopicExchange`:模式匹配路由 - `FanoutExchange`:广播路由 - `HeadersExchange`:头信息路由 4. **消费者绑定**: ```java @RabbitListener( queues = "order.queue", bindings = @QueueBinding( value = @Queue("dynamic.queue"), exchange = @Exchange(value = "dynamic.exchange", type = "topic"), key = "order.*" ) ) ``` ### 注意事项: 1. **幂等性声明**:多次声明相同名称的队列/交换机会被忽略(属性需一致) 2. **自动删除**:`autoDelete=true`时当所有消费者断开后自动删除 3. **独占队列**:`exclusive=true`时仅允许当前连接访问 4. **死信配置**:消息被拒绝/过期时自动转发到死信交换器
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值