Java 如何让Spring RabbitMQ创建新队列?
在我使用rabbit mq的(有限的)经验中,如果您为一个尚不存在的队列创建一个新的侦听器,那么该队列将自动创建。我试图使用SpringAMQP项目和RabbitMQ来设置一个侦听器,但是我得到了一个错误。这是我的xml配置: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: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.6和Spring 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.*");
}
}