使用传入的值作为@JmsListener 的目标参数

Using passed in Value for @JmsListener's destination paramter

有没有具体的方法可以做到这一点?我试图在这里找到解决方案,但找不到我需要的东西。我有一个 Spring 引导应用程序,它将接受来自命令行的多个参数。有问题的参数是队列名称(即目的地)。它可以是我们众多队列中的几个。 JmsListener 的形式是

@JmsListener(destination="dest_goes_here")
public void processOrder(Message message){. . .}

我有一个 class 基本上是这样的

 public class Arguments {
 private static queue
 private static antoherArg
 :
 :
getters and setters
 }

而我想说的是destination = Arguments.getQueue(),但是好像destination只能是一个static final变量?我假设这是因为错误提供了一个暗示这一点的小工具提示。

我也测试了它,因为我还有另一个 class 叫做 Constants,它显然包含常量,如果我将队列名称硬编码为 public static final String QUEUE = "MyQ"; 然后说 destination = Constants.QUEUE 没关系。

所以我假设我可以在我的监听器中做这样的事情 class private static final String QUEUE = Arguments.getQueue(); 但它也不喜欢那样。唉,难倒我了。

如果有人愿意分享知识,那么这里真的有两个问题。为什么 @JmsListener 可以将 destination 设置为我的第二个解决方案,而不是第一个和最后一个?

然后是主要问题(我希望您先回答这个问题)是,我可以使用什么策略将目标设置为源自命令行的变量(即动态)?

编辑:澄清一下,我不能将值保留在 Constants class 中,因为该值将来自命令行,需要传递给 JmsListener class 用作 destination.

这就是 Java 的工作原理,destination 必须是一个编译时常量表达式,函数调用不被视为一个。看看the official language specification for more details. EDIT: you can also look at this answer.

就你的第二个(也是更重要的)问题而言,我有几个建议给你。

首先,您可以从配置 属性 中读取队列名称,如下所示:destination="${jms.queue.name1}" 其中 jms.queue.name1 是您的配置 属性。然后,由于您正在使用 Spring 启动,您可以使用命令行参数来覆盖您的配置属性(请参阅 externalized configuration documentation for more details)。这样,您就可以在运行时通过将其作为命令行参数传递来指定队列名称,例如 --jms.queue.name1=foo.

其次,你可以使用programmatic listener registration,像这样:

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

    @Override
    public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
        SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
        endpoint.setId("myJmsEndpoint");
        endpoint.setDestination(Arguments.getQueue());
        endpoint.setMessageListener(message -> {
            // processing
        });
        registrar.registerEndpoint(endpoint);
    }
}