Rabbitmq Spring Amqp:将SimpleRoutingConnectionFactory与@RabbitListener混合使用
我有一个应用程序可以监听多个队列,它们在不同的vhost上声明。我使用SimpleRoutingConnectionFactory来存储connectionFactoryMap,我希望用@RabbitListener设置我的侦听器 根据Spring AMQP文件: 同样从1.4版开始,您可以配置路由连接 工厂位于一个简单的信息容器中。在这种情况下 队列名称用作查找键。例如,如果您配置 带有setQueueNames(“foo,bar”)的容器的查找键 “[foo,bar]”(无空格) 我使用了Rabbitmq Spring Amqp:将SimpleRoutingConnectionFactory与@RabbitListener混合使用,rabbitmq,spring-amqp,Rabbitmq,Spring Amqp,我有一个应用程序可以监听多个队列,它们在不同的vhost上声明。我使用SimpleRoutingConnectionFactory来存储connectionFactoryMap,我希望用@RabbitListener设置我的侦听器 根据Spring AMQP文件: 同样从1.4版开始,您可以配置路由连接 工厂位于一个简单的信息容器中。在这种情况下 队列名称用作查找键。例如,如果您配置 带有setQueueNames(“foo,bar”)的容器的查找键 “[foo,bar]”(无空格) 我使用了@
@RabbitListener(queues=“some key”)
。不幸的是,spring抱怨“查找键[null]”。见下文
18:52:44.528警告---[cTaskExecutor-1]
o、 s.a.r.l.SimpleMessageListenerContainer:消费者引发的异常,
如果连接工厂支持,则可以重新启动处理
java.lang.IllegalStateException:无法确定目标
位于的查找键[null]的ConnectionFactory
org.springframework.amqp.rabbit.connection.AbstractRoutingConnectionFactory.DeterminateTargetConnectionFactory(AbstractRoutingConnectionFactory.java:119)
在
org.springframework.amqp.rabbit.connection.AbstractRoutingConnectionFactory.createConnection(AbstractRoutingConnectionFactory.java:97)
在
org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils$1.createConnection(ConnectionFactoryUtils.java:90)
在
org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.doGetTransactionalResourceHolder(ConnectionFactoryUtils.java:140)
在
org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.getTransactionalResourceHolder(ConnectionFactoryUtils.java:76)
在
org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:472)
在
org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1306)
运行(Thread.java:745)
@SpringBootApplication
public class App2 implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(App2.class, args);
}
@Autowired
private IntegrationFlowContext flowContext;
@Autowired
private ConnectionFactory routingCf;
@Autowired
private RabbitTemplate template;
@Override
public void run(String... args) throws Exception {
// dynamically add a listener for queue qux
IntegrationFlow flow = IntegrationFlows.from(Amqp.inboundAdapter(this.routingCf, "qux").messageConverter(new Jackson2JsonMessageConverter()))
.handle(fooBean())
.get();
this.flowContext.registration(flow).register();
// now test it
SimpleResourceHolder.bind(this.routingCf, "[qux]");
this.template.convertAndSend("qux", 42);
this.template.convertAndSend("qux", "fizbuz");
this.template.convertAndSend("qux", new TestData(1, "test"));
SimpleResourceHolder.unbind(this.routingCf);
}
@Bean
RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(routingCf);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
}
@Bean
@Primary
public ConnectionFactory routingCf() {
SimpleRoutingConnectionFactory rcf = new SimpleRoutingConnectionFactory();
Map<Object, ConnectionFactory> map = new HashMap<>();
map.put("[foo,bar]", routedCf());
map.put("[baz]", routedCf());
map.put("[qux]", routedCf());
rcf.setTargetConnectionFactories(map);
return rcf;
}
@Bean
public ConnectionFactory routedCf() {
return new CachingConnectionFactory("127.0.0.1");
}
@Bean
public Foo fooBean() {
return new Foo();
}
public static class Foo {
@ServiceActivator
public void handleInteger(Integer in) {
System.out.println("int: " + in);
}
@ServiceActivator
public void handleString(String in) {
System.out.println("str: " + in);
}
@ServiceActivator
public void handleData(TestData data) {
System.out.println("TestData: " + data);
}
}
}
请显示您的配置-这对我来说很好
@SpringBootApplication
public class So42784471Application {
public static void main(String[] args) {
SpringApplication.run(So42784471Application.class, args);
}
@Bean
@Primary
public ConnectionFactory routing() {
SimpleRoutingConnectionFactory rcf = new SimpleRoutingConnectionFactory();
Map<Object, ConnectionFactory> map = new HashMap<>();
map.put("[foo,bar]", routedCf());
map.put("[baz]", routedCf());
rcf.setTargetConnectionFactories(map);
return rcf;
}
@Bean
public ConnectionFactory routedCf() {
return new CachingConnectionFactory("10.0.0.3");
}
@RabbitListener(queues = { "foo" , "bar" })
public void foobar(String in) {
System.out.println(in);
}
@RabbitListener(queues = "baz")
public void bazzer(String in) {
System.out.println(in);
}
}
嗨,格雷,谢谢你的快速回复。我希望你昨天能回答我的问题。你做到了!我编译并运行了您的代码片段#1,并获得了“java.lang.IllegalStateException:无法确定查找键[null]的目标ConnectionFactory”。有什么想法吗?我使用的是Spring boot 1.5.2,当然还创建了foo、bar和baz队列。我修改了一点。我更新了我的帖子。请看一看。有个警告一直在烦我。我想我错过了一些重要的事情。发生了一些奇怪的事情-根据stacktrace,消费者正试图通过
RoutingConnectionFactory
进行连接,但根据目标连接工厂,应该已经提取了。看起来容器是在队列名称设置之前启动的,这对我来说毫无意义。我也在使用Boot 1.5.2。也许你可以使用调试器来查看发生了什么?嗨@gary russell,我试过调试器,但还没有任何线索。我在帖子中发布了完整的堆栈跟踪。你有没有时间帮我在你的电脑上运行我的代码,看看你是否能重现这个问题?我刚刚把你的代码复制到我的应用程序中,它运行得很好(没有错误)。您是否在getConnectionFactory()
中设置了断点?查找是否未找到目标工厂?如果你想把你的整个项目发布到github或其他地方,我可以看看。
@SpringBootApplication
public class So42784471Application {
public static void main(String[] args) {
SpringApplication.run(So42784471Application.class, args);
}
@Bean
@Primary
public ConnectionFactory routing() {
SimpleRoutingConnectionFactory rcf = new SimpleRoutingConnectionFactory();
Map<Object, ConnectionFactory> map = new HashMap<>();
map.put("[foo,bar]", routedCf());
map.put("[baz]", routedCf());
rcf.setTargetConnectionFactories(map);
return rcf;
}
@Bean
public ConnectionFactory routedCf() {
return new CachingConnectionFactory("10.0.0.3");
}
@RabbitListener(queues = { "foo" , "bar" })
public void foobar(String in) {
System.out.println(in);
}
@RabbitListener(queues = "baz")
public void bazzer(String in) {
System.out.println(in);
}
}
@SpringBootApplication
public class So42784471Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(So42784471Application.class, args);
}
@Autowired
private IntegrationFlowContext flowContext;
@Autowired
private ConnectionFactory routingCf;
@Autowired
private RabbitTemplate template;
@Override
public void run(String... args) throws Exception {
// dynamically add a listener for queue qux
IntegrationFlow flow = IntegrationFlows.from(Amqp.inboundAdapter(this.routingCf, "qux"))
.handle(fooBean())
.get();
this.flowContext.registration(flow).register();
// now test it
SimpleResourceHolder.bind(this.routingCf, "[qux]");
this.template.convertAndSend("qux", 42);
this.template.convertAndSend("qux", "fizbuz");
SimpleResourceHolder.unbind(this.routingCf);
}
@Bean
@Primary
public ConnectionFactory routingCf() {
SimpleRoutingConnectionFactory rcf = new SimpleRoutingConnectionFactory();
Map<Object, ConnectionFactory> map = new HashMap<>();
map.put("[foo,bar]", routedCf());
map.put("[baz]", routedCf());
map.put("[qux]", routedCf());
rcf.setTargetConnectionFactories(map);
return rcf;
}
@Bean
public ConnectionFactory routedCf() {
return new CachingConnectionFactory("10.0.0.3");
}
@RabbitListener(queues = { "foo" , "bar" })
public void foobar(String in) {
System.out.println(in);
}
@RabbitListener(queues = "baz")
public void bazzer(String in) {
System.out.println(in);
}
@Bean
public Foo fooBean() {
return new Foo();
}
public static class Foo {
@ServiceActivator
public void handleInteger(Integer in) {
System.out.println("int: " + in);
}
@ServiceActivator
public void handleString(String in) {
System.out.println("str: " + in);
}
}
}