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

时间:2014-11-24 15:55:54

标签: java spring spring-amqp

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

所以对于每一对:

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

@RabbitListener(queues = "queue1")
public void handleMessage(MessageType1 msg) {...}

我需要在spring配置中输入一个条目:

<rabbit:queue name="queue1"/>

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

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

我认为有两种方法可以避免这种情况:

  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)
    
  2. 在同一队列中使用不同的消息POJO。因此,在MessageType1上发送MessageType2queue1,每个都根据有效负载类型到达不同的端点。实际上,这会创建一个单一的应用程序队列&#34;,类似于数据库模式:

    @RabbitListener(queues = "queue1")
    public void handleMessage1(MessageType1 msg) {...}
    
    @RabbitListener(queues = "queue1")
    public void handleMessage2(MessageType2 msg) {...}
    

    尝试这种方法会产生错误。

  3. 使用spring-amqp(1.4.0)目前是否可以实现上述任何一项,如果是这样的话?

1 个答案:

答案 0 :(得分:6)

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

将队列名称用作默认交换的路由键不被视为最佳做法,因为它将生产者和消费者联系起来。但我确实认为它有时被使用,所以请输入New Feature JIRA Issue我们会考虑它。

顺便说一句,你也可以在监听器旁边使用@Bean来避免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);
    } 
}

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

修改

这两项功能现已在1.5版本中提供。 @QueueBindingClass-level @RabbitListener