Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rabbitmq Spring Amqp:将SimpleRoutingConnectionFactory与@RabbitListener混合使用_Rabbitmq_Spring Amqp - Fatal编程技术网

Rabbitmq Spring Amqp:将SimpleRoutingConnectionFactory与@RabbitListener混合使用

Rabbitmq Spring Amqp:将SimpleRoutingConnectionFactory与@RabbitListener混合使用,rabbitmq,spring-amqp,Rabbitmq,Spring Amqp,我有一个应用程序可以监听多个队列,它们在不同的vhost上声明。我使用SimpleRoutingConnectionFactory来存储connectionFactoryMap,我希望用@RabbitListener设置我的侦听器 根据Spring AMQP文件: 同样从1.4版开始,您可以配置路由连接 工厂位于一个简单的信息容器中。在这种情况下 队列名称用作查找键。例如,如果您配置 带有setQueueNames(“foo,bar”)的容器的查找键 “[foo,bar]”(无空格) 我使用了@

我有一个应用程序可以监听多个队列,它们在不同的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)

  • 我做错什么了吗?如果队列属性用作查找键(用于连接工厂查找),我应该使用什么来指定要侦听的队列

  • 最终,我希望进行编程/动态侦听器设置。如果我使用“编程端点注册”,我是否应该删除“注释驱动的侦听器端点”?我喜欢“注释驱动的监听器端点”,因为监听器可以有多个消息句柄,以不同的传入数据类型作为参数,这非常干净整洁。如果使用编程端点注册,则必须解析消息输入变量,并根据消息类型/内容调用特定的自定义消息处理程序

  • 编辑: 嗨,加里, 我稍微修改了代码#2,以便它使用Jackson2JsonMessageConverter序列化类对象(在RabbitTemplatebean中),并使用它将它们反序列化回对象(在inboundAdapter中)。我还删除了@RabbitListener,因为在我的例子中,所有侦听器都将在运行时添加。现在fooBean可以毫无问题地接收integer、string和TestData消息了!留下的唯一问题是程序不断报告警告:

    “[erContainer#0-1]o.s.a.r.l.SimpleMessageListenerContainer:使用者引发的异常,如果连接工厂支持,处理可以重新启动

    java.lang.IllegalStateException:无法确定查找键[null]的目标ConnectionFactory。有关完整的stacktrace,请参见底部

    我错过什么了吗

    @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);
            }
    
        }
    
    }