【问题标题】:Spring AMQP - RabbitMQ connection is not created on application startupSpring AMQP - 应用程序启动时未创建 RabbitMQ 连接
【发布时间】:2020-11-16 11:38:12
【问题描述】:

我有一个 Spring Boot 应用程序,我的目标是在应用程序启动时声明队列、交换和绑定。应用程序将向各种队列生成消息,应用程序上没有消费者。

我已将这些依赖项包含在我的 pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
    <version>2.2.12.RELEASE</version>
</dependency>

我的配置类

@Configuration
public class RabbitConfiguration {

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("myhost", 5672);
        connectionFactory.setUsername("example_name");
        connectionFactory.setPassword("example_pass");
        return connectionFactory;
    }

    @Bean
    public AmqpAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    @Bean
    public Queue declareQueue() {
        return new Queue("test_queue", true, false, false);
    }

    @Bean
    public DirectExchange declareDirectExchange() {
        return new DirectExchange("test_direct_exchange", true, false);
    }

    @Bean
    public Declarables declareBindings() {

        return new Declarables(
            new Binding("test_queue", DestinationType.QUEUE, "test_direct_exchange", "test_routing_key", null)
        );
    }
}

我的问题是队列、交换和绑定不是在应用程序启动时创建的。 Spring Boot 甚至不打开连接。只有当我向队列生成消息时,才会创建连接、队列等。

【问题讨论】:

    标签: java spring spring-boot rabbitmq spring-amqp


    【解决方案1】:

    如果您想在应用启动期间强制声明并且没有任何消费者,您可以将执行器启动器添加到类路径中,或者简单地自己创建共享连接。

    @Bean
    ApplicationRunner runner(ConnectionFactory cf) {
        return args -> cf.createConnection().close();
    }
    

    这不会关闭连接;如果您想这样做,请致电cf.resetConnection()

    如果您希望应用程序在代理关闭时启动,请执行以下操作。

    @Bean
    ApplicationRunner runner(ConnectionFactory cf) {
        return args -> {
            boolean open = false;
            while(!open) {
                try {
                    cf.createConnection().close();
                    open = true;
                }
                catch (Exception e) {
                    Thread.sleep(5000);
                }
            }
        };
    }
    

    【讨论】:

      【解决方案2】:

      经过一番挖掘,我发现我缺少执行器依赖项。 所以添加这个依赖解决了我的问题

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

      奇怪的是,除非存在执行器依赖项,否则在应用程序启动时不会打开连接。

      【讨论】:

      • 只有在第一次需要的时候才会建立连接;当您发送消息或通过配置侦听器容器(例如@RabbitListener)时,默认情况下会自动启动。
      • 通过添加上述依赖项,在启动时建立连接,这正是我所需要的。我不需要配置侦听器容器,因为我的应用程序上没有任何消费者。我希望在应用程序启动时创建队列,因为在我的消费者应用程序上,我不希望我的消费者会尝试从不存在的队列中消费。
      • 如果您不需要执行器,另一种解决方案是添加ApplicationRunner bean。 @Bean ApplicationRunner runner(ConnectionFactory cf) { cf.createConnection(); };
      • 也可以,您可以将其发布为答案,以便人们更容易找到它。我认为您的解决方案更强大,因为我猜只是为此添加执行器依赖项并不好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 2021-03-01
      相关资源
      最近更新 更多