註解驅動的監聽器端點

接收非同步訊息最簡單的方式是使用註解驅動的監聽器端點基礎架構。簡而言之,它讓您可以將受管理 Bean 的方法公開為 Rabbit 監聽器端點。以下範例展示如何使用 @RabbitListener 註解

@Component
public class MyService {

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

}

前述範例的概念是,每當名為 myQueue 的佇列上有訊息可用時,就會相應地調用 processOrder 方法(在本例中,使用訊息的 payload)。

註解端點基礎架構會針對每個註解方法,在幕後使用 RabbitListenerContainerFactory 建立訊息監聽器容器。

在前述範例中,myQueue 必須已存在並綁定到某個交換器。只要應用程式上下文中存在 RabbitAdmin,佇列就可以自動宣告和綁定。

可以為註解屬性(queues 等)指定屬性佔位符(${some.property})或 SpEL 表達式(#{someExpression})。有關為何您可能使用 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 建立。您無法使用此技術宣告 Broker 命名的佇列;它們需要宣告為 Bean 定義;請參閱 容器與 Broker 命名的佇列。可以提供多個 QueueBinding 條目,讓監聽器監聽多個佇列。在第三個範例中,如有必要,會宣告一個名稱從屬性 my.queue 檢索的佇列,並使用佇列名稱作為路由金鑰,預設綁定到預設交換器。

自 2.0 版本起,@Exchange 註解支援任何交換器類型,包括自訂類型。如需更多資訊,請參閱 AMQP 概念

當您需要更進階的設定時,可以使用一般的 @Bean 定義。

請注意第一個範例中交換器上的 ignoreDeclarationExceptions。例如,這允許綁定到可能具有不同設定(例如 internal)的現有交換器。預設情況下,現有交換器的屬性必須匹配。

從 2.0 版本開始,您現在可以將佇列綁定到具有多個路由金鑰的交換器,如下列範例所示

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

您也可以在 @QueueBinding 註解中為佇列、交換器和綁定指定引數,如下列範例所示

@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。與所有此類宣告一樣,如果佇列已存在,則引數必須與佇列上的引數匹配。對於標頭交換器,我們設定綁定引數以匹配標頭 thing1 設定為 somevalue 的訊息,並且 thing2 標頭必須存在且具有任何值。x-match 引數表示必須滿足兩個條件。

引數名稱、值和類型可以是屬性佔位符(${…​})或 SpEL 表達式(#{…​})。name 必須解析為 Stringtype 的表達式必須解析為 Class 或類別的完整限定名稱。value 必須解析為可以由 DefaultConversionService 轉換為該類型的事物(例如前述範例中的 x-message-ttl)。

如果名稱解析為 null 或空 String,則會忽略該 @Argument