Java 如何让Spring RabbitMQ创建新队列?

Java 如何让Spring RabbitMQ创建新队列?,java,spring,rabbitmq,amqp,Java,Spring,Rabbitmq,Amqp,在我使用rabbit mq的(有限的)经验中,如果您为一个尚不存在的队列创建一个新的侦听器,那么该队列将自动创建。我试图使用SpringAMQP项目和RabbitMQ来设置一个侦听器,但是我得到了一个错误。这是我的xml配置: <rabbit:connection-factory id="rabbitConnectionFactory" host="172.16.45.1" username="test" password="password" /> <rabbit:list

在我使用rabbit mq的(有限的)经验中,如果您为一个尚不存在的队列创建一个新的侦听器,那么该队列将自动创建。我试图使用SpringAMQP项目和RabbitMQ来设置一个侦听器,但是我得到了一个错误。这是我的xml配置:

<rabbit:connection-factory id="rabbitConnectionFactory" host="172.16.45.1" username="test" password="password" />

<rabbit:listener-container connection-factory="rabbitConnectionFactory"  >
    <rabbit:listener ref="testQueueListener" queue-names="test" />
</rabbit:listener-container>

<bean id="testQueueListener" class="com.levelsbeyond.rabbit.TestQueueListener"> 
</bean>

从堆栈跟踪中可以看出,队列是在“被动”模式下创建的——有人能指出我如何在不使用被动模式的情况下创建队列,这样我就看不到这个错误了吗?还是我遗漏了什么?

您能在连接标记之后,但在侦听器之前添加以下内容吗:

<rabbit:queue name="test" auto-delete="true" durable="false" passive="false" />

不幸的是,根据XSD模式,被动属性(上面列出)无效。然而,在我看到的每个队列声明实现中,被动都是一个有效的队列声明参数。我很好奇这是否会奏效,或者他们是否计划在未来支持它

以下是队列声明选项的完整列表:

下面是SpringRabbit模式的完整XSD(包括注释):
似乎解决我问题的方法是添加一个管理员。以下是我的xml:

<rabbit:listener-container connection-factory="rabbitConnectionFactory"  >
    <rabbit:listener ref="orderQueueListener" queues="test.order" />
</rabbit:listener-container>

<rabbit:queue name="test.order"></rabbit:queue>

<rabbit:admin id="amqpAdmin" connection-factory="rabbitConnectionFactory"/>

<bean id="orderQueueListener" class="com.levelsbeyond.rabbit.OrderQueueListener">   
</bean>


较旧的线程,但这仍然在Google上显示得相当高,因此这里有一些较新的信息:

2015-11-23 自从使用Spring消息传递和Spring Amqp 1.4.5.RELEASE和Spring Rabbit 1.4.5.RELEASE发布Spring 4.2.x以来,通过@Configuration类声明交换、队列和绑定变得非常简单一些注释:

@EnableRabbit
@Configuration
@PropertySources({
    @PropertySource("classpath:rabbitMq.properties")
})
public class RabbitMqConfig {    
    private static final Logger logger = LoggerFactory.getLogger(RabbitMqConfig.class);

    @Value("${rabbitmq.host}")
    private String host;

    @Value("${rabbitmq.port:5672}")
    private int port;

    @Value("${rabbitmq.username}")
    private String username;

    @Value("${rabbitmq.password}")
    private String password;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);

        logger.info("Creating connection factory with: " + username + "@" + host + ":" + port);

        return connectionFactory;
    }

    /**
     * Required for executing adminstration functions against an AMQP Broker
     */
    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
    }

    /**
     * This queue will be declared. This means it will be created if it does not exist. Once declared, you can do something
     * like the following:
     * 
     * @RabbitListener(queues = "#{@myDurableQueue}")
     * @Transactional
     * public void handleMyDurableQueueMessage(CustomDurableDto myMessage) {
     *    // Anything you want! This can also return a non-void which will queue it back in to the queue attached to @RabbitListener
     * }
     */
    @Bean
    public Queue myDurableQueue() {
        // This queue has the following properties:
        // name: my_durable
        // durable: true
        // exclusive: false
        // auto_delete: false
        return new Queue("my_durable", true, false, false);
    }

    /**
     * The following is a complete declaration of an exchange, a queue and a exchange-queue binding
     */
    @Bean
    public TopicExchange emailExchange() {
        return new TopicExchange("email", true, false);
    }

    @Bean
    public Queue inboundEmailQueue() {
        return new Queue("email_inbound", true, false, false);
    }

    @Bean
    public Binding inboundEmailExchangeBinding() {
        // Important part is the routing key -- this is just an example
        return BindingBuilder.bind(inboundEmailQueue()).to(emailExchange()).with("from.*");
    }
}
一些资料来源和文档有助于:


  • 注意:看起来我错过了一个版本——从Spring AMQP 1.5开始,事情变得更加简单,因为您可以在侦听器上声明完全绑定

    Spring Boot 2.1.6Spring AMQP 2.1.7开始,如果队列不存在,您可以在启动期间创建队列:

    @组件
    公共类队列配置{
    私人AmqpAdmin AmqpAdmin;
    公共队列配置(AmqpAdmin AmqpAdmin){
    this.amqpAdmin=amqpAdmin;
    }
    @施工后
    public void createQueues(){
    amqpAdmin.declareQueue(新队列(“队列1”,true));
    amqpAdmin.declareQueue(新队列(“队列二”,true));
    }
    }
    
    不幸的是,我得到一个错误,启动时队列元素中不允许使用“被动”属性。“declare”方法使用被动参数是很奇怪的,但我似乎无法用xml定义它。对不起,我太密集了,我看不出我遗漏了什么。我知道你在说根据xsd它不是有效的xml,我可以忽略eclipse给我的错误-但我实际上也得到了一个运行时错误。没关系。我的中间名是稠密的。:-)我想我们说的是同一件事。IMHO,如果是完整的兔子接口,则应存在上述被动参数。Spring RabbitMQ缺少它。我会向他们提交一份bug报告,并在你的bug报告中链接回这个问题。他们可能知道我们都遗漏了什么,或者只是一个合理的遗漏。是的,您必须在配置中添加一个
    RabbitAdmin
    ,以自动声明队列、交换和绑定。此外,在向队列发送消息之前,不会声明队列。它也在Java注释模式下工作:添加自动连线
    AmqpAdmin
    并使用专用方法声明队列,在不存在时自动创建队列!使用rabbit:listener元素,如何让rabbit声明一个随机命名的队列以用于扇出交换?您可以通过方法调用创建bean并再次创建对象。
    <rabbit:listener-container connection-factory="rabbitConnectionFactory"  >
        <rabbit:listener ref="orderQueueListener" queues="test.order" />
    </rabbit:listener-container>
    
    <rabbit:queue name="test.order"></rabbit:queue>
    
    <rabbit:admin id="amqpAdmin" connection-factory="rabbitConnectionFactory"/>
    
    <bean id="orderQueueListener" class="com.levelsbeyond.rabbit.OrderQueueListener">   
    </bean>
    
    @EnableRabbit
    @Configuration
    @PropertySources({
        @PropertySource("classpath:rabbitMq.properties")
    })
    public class RabbitMqConfig {    
        private static final Logger logger = LoggerFactory.getLogger(RabbitMqConfig.class);
    
        @Value("${rabbitmq.host}")
        private String host;
    
        @Value("${rabbitmq.port:5672}")
        private int port;
    
        @Value("${rabbitmq.username}")
        private String username;
    
        @Value("${rabbitmq.password}")
        private String password;
    
        @Bean
        public ConnectionFactory connectionFactory() {
            CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
            connectionFactory.setUsername(username);
            connectionFactory.setPassword(password);
    
            logger.info("Creating connection factory with: " + username + "@" + host + ":" + port);
    
            return connectionFactory;
        }
    
        /**
         * Required for executing adminstration functions against an AMQP Broker
         */
        @Bean
        public AmqpAdmin amqpAdmin() {
            return new RabbitAdmin(connectionFactory());
        }
    
        /**
         * This queue will be declared. This means it will be created if it does not exist. Once declared, you can do something
         * like the following:
         * 
         * @RabbitListener(queues = "#{@myDurableQueue}")
         * @Transactional
         * public void handleMyDurableQueueMessage(CustomDurableDto myMessage) {
         *    // Anything you want! This can also return a non-void which will queue it back in to the queue attached to @RabbitListener
         * }
         */
        @Bean
        public Queue myDurableQueue() {
            // This queue has the following properties:
            // name: my_durable
            // durable: true
            // exclusive: false
            // auto_delete: false
            return new Queue("my_durable", true, false, false);
        }
    
        /**
         * The following is a complete declaration of an exchange, a queue and a exchange-queue binding
         */
        @Bean
        public TopicExchange emailExchange() {
            return new TopicExchange("email", true, false);
        }
    
        @Bean
        public Queue inboundEmailQueue() {
            return new Queue("email_inbound", true, false, false);
        }
    
        @Bean
        public Binding inboundEmailExchangeBinding() {
            // Important part is the routing key -- this is just an example
            return BindingBuilder.bind(inboundEmailQueue()).to(emailExchange()).with("from.*");
        }
    }