Spring AMQP:如何避免手动声明多个队列?

Ami*_*iri 5 java spring spring-amqp

创建了一个基本的spring-amqp设置后,我看到对于我要发送的每种类型的消息(使用消息POJO),我需要在spring配置中声明队列.

所以对于每一对:

amqpTemplate.convertAndSend("queue1", new MessageType1(...));

@RabbitListener(queues = "queue1")
public void handleMessage(MessageType1 msg) {...}
Run Code Online (Sandbox Code Playgroud)

我需要一个Spring配置中的条目,如下所示:

<rabbit:queue name="queue1"/>
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎是多余的.如果我想到像HTTP url这样的队列,而不是用它来声明一个控制器@RequestMapping("/some-url"),那么就不必/some-url在配置中的其他地方声明.

如果最终应用程序将有许多类型的消息通过代理,那将只会使配置膨胀.

我看到两种避免这种情况的方法:

  1. 自动声明每个带注释的侦听器端点的队列.即,如果存在带注释的侦听器端点@RabbitListener(queues = "hello"),则可以推断出hello应该声明队列.我认为可能已经是这种情况,但是当我从上下文配置中删除队列时,我收到以下错误:

    WARN  BlockingQueueConsumer - Failed to declare queue:hello
    WARN  BlockingQueueConsumer - Queue declaration failed; retries left=2
    org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[hello]
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:479)
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:400)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1022)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在同一队列中使用不同的消息POJO.所以同时发送MessageType1MessageType2queue1,每达到不同的端点,基于有效载荷类型.实际上,这会创建一个单独的"应用程序队列",类似于数据库模式:

    @RabbitListener(queues = "queue1")
    public void handleMessage1(MessageType1 msg) {...}
    
    @RabbitListener(queues = "queue1")
    public void handleMessage2(MessageType2 msg) {...}
    
    Run Code Online (Sandbox Code Playgroud)

    尝试这种方法产生了一个错误.

使用spring-amqp(1.4.0)是否有上述任何一种,如果是这样的话怎么样?

Gar*_*ell 6

目前无法自动声明@RabbitListener队列,但这听起来像是一个合理的请求.当然,单独声明队列可能还不够; 虽然它将""与队列名称作为路由键绑定到默认交换,但任何更复杂的绑定都需要额外的配置.

使用队列名称作为具有默认交换的路由密钥不被视为最佳实践,因为它将生产者和消费者耦合在一起.但我确实认为它有时被使用,所以请输入一个新功能JIRA问题,我们会考虑它.

顺便说一句,您还可以@Bean在侦听器旁边使用s来避免XML配置.

您的第二个请求可以由委派消息监听器实现:

@RabbitListener(queues = "queue1")
public void handleMessage(Object o) {
    if (o instanceof Type1) {
        delegate.type1((Type1) o);
    }
    else if (o instanceof Type2) {
        delegate.type2((Type2) o);
    } 
}
Run Code Online (Sandbox Code Playgroud)

我一直在考虑提供这样一个听众(以更通用的方式).再次,请打开一个新的功能问题.

编辑

这两个功能现在都可以在1.5版本中找到.@QueueBinding班级@RabbitListener.