【问题标题】:create queue/exchange/binding/listener at run time in spring boot rabbitmq在 Spring Boot RabbitMQ 运行时创建队列/交换/绑定/侦听器
【发布时间】:2018-02-05 07:48:01
【问题描述】:

我正在使用带有rabbitmq 的spring-boot。我创建了一些固定的队列/交换/绑定/侦听器。

监听器创建如下:

@RabbitListener
public void foo(String msg) {...}

现在我想在每个用户登录时与交换/绑定/侦听器一起在运行时为每个用户创建队列,并在用户注销时销毁这些队列。我如何在 spring-boot 中做到这一点。

【问题讨论】:

    标签: java spring-boot spring-rabbit


    【解决方案1】:

    你不能用@RabbitListener 轻松做到这一点(你可以,但你必须为每个创建一个新的子应用程序上下文)。

    您可以使用RabbitAdmin 动态创建队列和绑定,并为每个新队列创建一个消息侦听器容器。

    编辑

    这是使用@RabbitListener 和子上下文的一种方法;使用 Spring Boot 时,ListenerConfig 类不能与启动应用程序本身在同一个包(或子包)中。

    @SpringBootApplication
    public class So48617898Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So48617898Application.class, args).close();
        }
    
        private final Map<String, ConfigurableApplicationContext> children = new HashMap<>();
    
        @Bean
        public ApplicationRunner runner(RabbitTemplate template, ApplicationContext context) {
            return args -> {
                Scanner scanner = new Scanner(System.in);
                String line = null;
                while (true) {
                    System.out.println("Enter a new queue");
                    line = scanner.next();
                    if ("quit".equals(line)) {
                        break;
                    }
                    children.put(line, addNewListener(line, context));
                    template.convertAndSend(line, "test to " + line);
                }
                scanner.close();
                for (ConfigurableApplicationContext ctx : this.children.values()) {
                    ctx.stop();
                }
            };
        }
    
        private ConfigurableApplicationContext addNewListener(String queue, ApplicationContext context) {
            AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
            child.setParent(context);
            ConfigurableEnvironment environment = child.getEnvironment();
            Properties properties = new Properties();
            properties.setProperty("queue.name", queue);
            PropertiesPropertySource pps = new PropertiesPropertySource("props", properties);
            environment.getPropertySources().addLast(pps);
            child.register(ListenerConfig.class);
            child.refresh();
            return child;
        }
    
    }
    

    @Configuration
    @EnableRabbit
    public class ListenerConfig {
    
        @RabbitListener(queues = "${queue.name}")
        public void listen(String in, @Header(AmqpHeaders.CONSUMER_QUEUE) String queue) {
            System.out.println("Received " + in + " from queue " + queue);
        }
    
        @Bean
        public Queue queue(@Value("${queue.name}") String name) {
            return new Queue(name);
        }
    
        @Bean
        public RabbitAdmin admin(ConnectionFactory cf) {
            return new RabbitAdmin(cf);
        }
    
    }
    

    【讨论】:

    • 你能举个例子吗?
    • 查看我的编辑以了解如何使用@RabbitListeners 进行操作。
    • @GaryRussell 当我尝试使用此逻辑创建具有独占和自动删除功能的队列时,它会引发异常 - channel error; protocol method: #method&lt;channel.close&gt;(reply-code=405, reply-text=RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'ewfasdfas-asdtweasfd-11703B' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original declaration
    • 这就是我装饰我的听众的方式 - @RabbitListener(bindings = @QueueBinding(value = @org.springframework.amqp.rabbit.annotation.Queue(value = "${queue.name}", durable = "true", autoDelete = "true", exclusive="true", arguments = @Argument(name = "x-expires", value = "20000", type = "java.lang.Integer")), exchange = @Exchange(value = "${exchange.name}", ignoreDeclarationExceptions = "true"), key = "${routing.key}"))
    • 不要评论 3 年前的答案,不要将代码放入 cmets;它渲染得不好。这个错误对我来说似乎很清楚;现有队列不是独占的,或者是在不同的连接上声明的。如果您仍然无法弄清楚,请提出一个显示您的配置的新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    • 2020-04-30
    • 2011-05-31
    • 1970-01-01
    • 2016-05-28
    • 2017-11-24
    相关资源
    最近更新 更多