此版本仍在开发中,目前尚不稳定。如需最新稳定版本,请使用 Spring AMQP 4.0.2spring-doc.cadn.net.cn

基于注解驱动的监听器端点

接收消息的最简单异步方式是使用带注解的监听器端点基础设施。简而言之,它允许您将一个托管 Bean 的方法暴露为 Rabbit 监听器端点。以下示例展示了如何使用 @RabbitListener 注解:spring-doc.cadn.net.cn

@Component
public class MyService {

    @RabbitListener(queues = "myQueue")
    public void processOrder(String data) {
        ...
    }

}

前面示例的核心思想是,每当名为 myQueue 的队列中有消息可用时,便会相应地调用 processOrder 方法(在此情况下,以消息的负载作为参数)。spring-doc.cadn.net.cn

注解端点基础设施会为每个注解方法在后台创建一个消息监听容器,方法是使用 RabbitListenerContainerFactoryspring-doc.cadn.net.cn

在前面的示例中,myQueue 必须已存在并绑定到某个交换机。只要应用程序上下文中存在一个 RabbitAdmin,队列即可自动声明并绑定。spring-doc.cadn.net.cn

属性占位符(${some.property})或 SpEL 表达式(#{someExpression})可以用于注解属性(queues 等)。有关为何可能使用 SpEL 而非属性占位符的示例,请参阅 监听多个队列。以下列表展示了三种声明 Rabbit 消息监听器的方法:
@Component
public class MyService {

  @RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "myQueue", durable = "true"),
        exchange = @Exchange(value = "auto.exch", ignoreDeclarationExceptions = "true"),
        key = "orderRoutingKey")
  )
  public void processOrder(Order order) {
    ...
  }

  @RabbitListener(bindings = @QueueBinding(
        value = @Queue,
        exchange = @Exchange(value = "auto.exch"),
        key = "invoiceRoutingKey")
  )
  public void processInvoice(Invoice invoice) {
    ...
  }

  @RabbitListener(queuesToDeclare = @Queue(name = "${my.queue}", durable = "true"))
  public String handleWithSimpleDeclare(String data) {
      ...
  }

}

在第一个示例中,如果需要,会自动声明一个队列 myQueue(持久化),并将其与交换机一同创建,然后使用路由键将其绑定到交换机上。在第二个示例中,会声明并绑定一个匿名(独占、自动删除)队列;队列名称由框架使用 Base64UrlNamingStrategy 自动生成。您无法使用此方法声明代理命名的队列;它们需要作为 Bean 定义进行声明;参见 容器和代理命名队列。多个 QueueBinding 条目可以提供,使监听器能够监听多个队列。在第三个示例中,会根据属性 my.queue 中获取的名称声明一个队列(如需),并使用默认绑定方式将该队列绑定到默认交换机,此时路由键即为队列名称。spring-doc.cadn.net.cn

自版本 2.0 起,@Exchange 注解支持任何交换类型,包括自定义类型。有关更多信息,请参阅 AMQP 概念spring-doc.cadn.net.cn

当您需要更高级的配置时,可以使用常规 @Bean 定义。spring-doc.cadn.net.cn

注意第一个示例中交换机上的 ignoreDeclarationExceptions
这允许例如绑定到一个已存在的交换机,该交换机可能具有不同的设置(如 internal)。
默认情况下,现有交换机的属性必须匹配。spring-doc.cadn.net.cn

从版本 2.0 开始,现在您可以使用多个路由键将队列绑定到交换机,如下所示的示例:spring-doc.cadn.net.cn

...
    key = { "red", "yellow" }
...

你还可以在 @QueueBinding 注解中为队列、交换机和绑定指定参数,如下例所示:spring-doc.cadn.net.cn

@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "auto.headers", autoDelete = "true",
                        arguments = @Argument(name = "x-message-ttl", value = "10000",
                                                type = "java.lang.Integer")),
        exchange = @Exchange(value = "auto.headers", type = ExchangeTypes.HEADERS, autoDelete = "true"),
        arguments = {
                @Argument(name = "x-match", value = "all"),
                @Argument(name = "thing1", value = "somevalue"),
                @Argument(name = "thing2")
        })
)
public String handleWithHeadersExchange(String foo) {
    ...
}

注意,队列的 x-message-ttl 参数被设置为 10 秒钟。
由于参数类型不是 String,我们必须指定其类型——在此情况下为 Integer
与所有此类声明一样,如果队列已存在,则参数必须与队列上的参数相匹配。
对于头交换(header exchange),我们将绑定参数设置为匹配那些具有 thing1 头部且值为 somevalue 的消息,并且
thing2 头部必须存在,且可取任意值。
x-match 参数表示两个条件都必须满足。spring-doc.cadn.net.cn

参数名称、值和类型可以是属性占位符(${…​})或 SpEL 表达式(#{…​})。name 必须解析为一个 Stringtype 的表达式必须解析为一个 Class 或某类的完全限定名。 value 必须解析为某种可由 DefaultConversionService 转换为指定类型(如前述示例中的 x-message-ttl)的对象。spring-doc.cadn.net.cn

如果一个名称解析为 null 或空的 String,则该 @Argument 将被忽略。spring-doc.cadn.net.cn