@RabbitListener - 从属性定义队列

@RabbitListener - defining queues from properties

可以使用逗号分隔 属性 来定义要侦听的队列吗?目的是能够在不更改代码的情况下更改队列名称和队列数量。

我在 application.properties 中定义了队列,如下所示:

my.aggregate.queues=/some/queue,/some/other/queue

我可以使用 SpEL 将队列名称作为列表包含在内:

@Value("#{'${my.aggregate.queues}'.split(',')}")

但是,当我尝试使用 @RabbitListener 批注监听队列时,我发现我必须单独定义队列。使用

@RabbitListener(queues = { "#{'${my.aggregate.queues}'.split(',')}" })

导致队列名称被解析为字符串数组,但无法使用:

@RabbitListener can't resolve '[Ljava.lang.String;@5396eeb1' as either a String or a Queue

我尝试过各种其他 SpEL 组合,但均未成功。有没有办法使用 SpEL 动态定义队列?

是的; SpEL 会将队列名称数组放在 queues 数组的第一个元素中。

如果您打开 JIRA issue,我们有机会修复下周发布的 1.5 版本。

我认为我们需要接受一个计算结果为逗号分隔字符串的表达式,然后在处理注释时进行拆分。

编辑:

但是,我刚刚意识到 RabbitMQ 允许您在其中创建带有逗号的队列,所以也许我们应该只将第一个数组元素本身作为一个数组来处理。

这是该问题的编程解决方法:

private MethodRabbitListenerEndpoint createEndpoint() {
  MethodRabbitListenerEndpoint endpoint = new MethodRabbitListenerEndpoint();

  endpoint.setQueueNames(queues.toArray(new String[] {})); // auto wired in
  endpoint.setAdmin(admin);
  endpoint.setBean(interceptor);
  endpoint.setId(ENDPOINT_ID);

  endpoint.setMessageHandlerMethodFactory(createMethodFactory());

  endpoint.setMethod(ReflectionUtils.findMethod(MyInterceptor.class, “myMethod”,
      MyAbstractJsonSuperclass.class, Channel.class));

  SimpleMessageListenerContainer container = listenerFactory.createListenerContainer(endpoint);
  container.setupMessageListener(admin.getRabbitTemplate());

  return endpoint;
}

private MessageHandlerMethodFactory createMethodFactory() {
  DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();

  messageHandlerMethodFactory.setMessageConverter(converter); // custom json converter
  messageHandlerMethodFactory.afterPropertiesSet();

  return messageHandlerMethodFactory;
}

如果您在系统变量"cluster.name"中使用队列名称,并且需要使用条件自定义名称值,您可以使用Spel:

@RabbitListener(queues = "#{'${cluster.name}' != null?'batch.queue-${cluster.name}':'batch.queue'}", containerFactory = "listenerContainerFactory")