【问题标题】:Dynamic Queues on RabbitListener AnnotationRabbitListener 注解上的动态队列
【发布时间】:2018-04-18 22:20:28
【问题描述】:

我想使用特定模式的队列名称,例如project.{queue-name}.queue。为了保持这种模式的稳固性,我编写了一个帮助类来从一个简单的标识符生成这个名称。因此,foo 将生成一个名为project.foo.queue 的队列。很简单。

但是,注释 RabbitListener 需要一个常量字符串,并在使用我的帮助程序类时给我一个错误。如何使用RabbitListener 注释来实现这一点(或者可能是另一种方法)?

@Component
public class FooListener {

    // it doesn't work
    @RabbitListener(queues = QueueName.for("foo"))
    // it works
    @RabbitListener(queues = "project.foo.queue")
    void receive(final FooMessage message) {
       // ...
    }
}

【问题讨论】:

  • 上下文从何而来?环境变量?
  • 我已经为“queue-name”更改了“context”以进行澄清。这只是一个名字。但我想加强名称模式。

标签: java spring rabbitmq


【解决方案1】:

要创建和侦听由动态 UUID 构造的队列名称,您可以使用 random.uuid

问题是这必须在一个地方被捕获到一个Java变量,因为a new random value would be generated each time the property is referenced

解决方案是使用Spring Expression Language (SpEL) 调用提供配置值的函数,例如:

@RabbitListener(queues = "#{configureAMQP.getControlQueueName()}")
void receive(final FooMessage message) {
       // ...
}

用这样的东西创建队列:

@Configuration
public class ConfigureAMQP {

    @Value("${controlQueuePrefix}-${random.uuid}")
    private String controlQueueName;

    public String getControlQueueName() {
        return controlQueueName;
    }

    @Bean
    public Queue controlQueue() {
        System.out.println("controlQueue(): controlQueueName=" + controlQueueName);
        return new Queue(controlQueueName, true, true, true);
    }

}

请注意,SpEL 中使用的必要 bean 是基于 @Configuration 类隐式创建的(对拼写 ConfigureAMQP -> configureAMQP 略有改动)。

【讨论】:

  • 这似乎可以用作注释,这很棒。但我不知道如何将它连接到创建具有相同随机名称的队列的配置。
  • @nobar 假设您使用的是 Spring Boot,您可以轻松地在 application.yml 或属性文件中使用相同的随机属性 - 例如 queue-name: someprefix-${random-uuid}。您可以在代码中的任何位置使用 value 注释或 SPEL。
  • 我很欣赏这个建议——它似乎应该适用于我的情况(尽管我仍在努力争取 Spring 试图让它发挥作用)。它不像 OP 试图做的那样普遍,但也许它表明使用正确的魔豆可以制定一个精心制作的通用解决方案......
  • 顺便说一句:我假设你的意思是输入${random.uuid}——对吗?我很难找到这方面的文档(使用任何一种拼写)。
  • 不客气 - 是的,应该是 ${random.uuid}Documentationjavadoc。如果您能进一步解释您的问题,我可以扩展解决方案。
【解决方案2】:

声明一个magic bean,在本例中隐式命名为queueName

@Component
public class QueueName {
    public String buildFor(String name) {
        return "project."+name+".queue";
    }
}

使用将在运行时评估的“常量字符串”访问它:

@RabbitListener(queues = "#{queueName.buildFor(\"foo\")}")

【讨论】:

    【解决方案3】:

    如果 {queue-name} 来自 yml 文件 - 它应该可以工作:

    @RabbitListener(queues = "${queue-name}")
    public void receiveMessage(FooMessage message) {
    
    }
    

    Spring 将从application.yml 注入值。

    【讨论】:

    • 优秀的反应,简单的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多