在使用rabbit-mq的(有限)经验中,如果为尚不存在的队列创建新的侦听器,则会自动创建队列.我正在尝试使用带有rabbit-mq的Spring AMQP项目来设置一个监听器,而我正在收到错误.这是我的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>
我在RabbitMq日志中得到了这个:
=ERROR REPORT==== 3-May-2013::23:17:24 ===
connection <0.1652.0>, channel 1 - soft error:
{amqp_error,not_found,"no queue 'test' in vhost '/'",'queue.declare'}
和AMQP类似的错误:
2013-05-03 23:17:24,059 ERROR [org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer] (SimpleAsyncTaskExecutor-1) - Consumer received fatal exception on startup
org.springframework.amqp.rabbit.listener.FatalListenerStartupException: Cannot prepare queue for listener. Either the queue doesn't exist or the broker will not allow us to use it.
从堆栈跟踪看来,队列是以“被动”模式创建的 – 任何人都可以指出我如何创建不使用被动模式的队列,所以我没有看到这个错误?还是我错过了别的什么?
解决方法:
较旧的帖子,但这仍然在谷歌上显得相当高,所以这里有一些新的信息:
2015年11月23日
从Spring 4.2.x开始使用Spring-Messaging和Spring-Amqp 1.4.5.RELEASE和Spring-Rabbit 1.4.5.RELEASE,通过@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 annotations
> Declaring/configuration RabbitMQ for queue/binding support
> Direct exchange binding (for when routing key doesn’t matter)
注意:看起来我错过了一个版本 – 从Spring AMQP 1.5开始,事情变得更加容易,因为你可以在听众声明完整的绑定!