我有一个关于通过XML连接使用spring-amqp以及通过在java代码中创建各种对象的问题。
通过XML和Java代码执行此操作非常简单,并且在大多数情况下一直很适合我。但是,在经纪人中断后(通过关闭并重新启动我的经纪人进行模拟),我得到了两个不同的结果。
使用XML连接创建spring-amqp对象时,一切正常。重新建立连接,重新创建队列并重新开始接收消息。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:ctx="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd">
<rabbit:connection-factory id="connectionFactory"
addresses="192.168.1.10:5672"
username="guest"
password="guest"
/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:queue name="testQueue" id="testQueue" auto-declare="true" auto-delete="true" exclusive="false"/>
<rabbit:fanout-exchange name="testExchange" id="testExchange" >
<rabbit:bindings>
<rabbit:binding queue="testQueue" />
</rabbit:bindings>
</rabbit:fanout-exchange>
<bean class="TestConsumer" id="testConsumer" />
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="testQueue" ref="testConsumer" method="inbound" />
</rabbit:listener-container>
</beans>
但是,当使用Java创建spring-amqp对象时,我遇到了问题。重新建立连接,但是我立即点击报告未找到队列的异常。管理员不会尝试重新创建队列,在几个例外之后,侦听器容器就会停止。
public static void main(String[] args) {
CachingConnectionFactory cf = new CachingConnectionFactory("192.168.1.10", 5672);
RabbitAdmin admin = new RabbitAdmin(cf);
FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);
Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);
admin.declareBinding(BindingBuilder.bind(testQueue).to(testExchange));
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(cf);
container.setRabbitAdmin(admin);
container.setQueues(testQueue);
container.setMessageListener(new MessageListenerAdapter() {
public void handleMessage(String text) {
System.out.println("Received : " + text);
}
});
container.afterPropertiesSet();
container.start();
try {
Thread.sleep(600000L);
} catch(Exception e) {
e.printStackTrace();
}
container.stop();
container.destroy();
System.out.println("Exiting");
}
这是我在重新建立连接之后和侦听器容器退出之前看到的(三次或四次)异常:
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'testQueue' in vhost '/', class-id=50, method-id=10)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:478)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:315)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:552)
我认为XML布线案例和纯Java案例应该等效,但显然情况并非如此。我不确定是否 我的Java案例中缺少某些内容,或者是否仅支持此内容。
我当然可以检测到侦听器容器的失败,并使用admin重新声明队列,但是因为这不是必需的XML有线示例,我想知道我可能会遗漏什么。
使用org.springframework.amqp.spring-rabbit 1.4.5.RELEASE
答案 0 :(得分:1)
管理员需要一个Spring Application Context来自动声明元素(队列等)。
它在连接工厂中注册连接侦听器,并且在建立新连接时,它会在应用程序上下文中查找所有队列等并注册它们。
因为你正在使用&#34; pure&#34; java(没有Spring Application Context),这种机制无法工作。
您可以使用Spring Java Configuration替换XML(使用@Bean
定义),或者您必须使用连接工厂注册自己的类来执行声明。
请参阅管理源代码for how he registers the listener和initialize method了解他如何进行声明。
你只需要做你的
FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);
Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);
在听众中。