異常處理

預設情況下,如果帶註解的監聽器方法丟擲異常,異常會被拋給容器,並且訊息會被重新入隊並重新投遞、丟棄或路由到死信交換器,具體取決於容器和經紀商的配置。傳送者不會收到任何返回。

從版本 2.0 開始,該 @RabbitListener 註解有兩個新屬性:errorHandlerreturnExceptions

這些屬性預設未配置。

你可以使用 errorHandler 來提供 RabbitListenerErrorHandler 實現的 bean 名稱。這個函式式介面有一個方法,如下所示:

@FunctionalInterface
public interface RabbitListenerErrorHandler {

    Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
              ListenerExecutionFailedException exception) throws Exception;

}

如你所見,你可以訪問從容器接收到的原始訊息、訊息轉換器產生的 spring-messaging Message<?> 物件,以及監聽器丟擲的異常(包裝在 ListenerExecutionFailedException 中)。錯誤處理器可以返回某個結果(作為回覆傳送),或者丟擲原始異常或新異常(異常將被拋給容器或返回給傳送者,具體取決於 returnExceptions 設定)。

returnExceptions 屬性,當為 true 時,會導致異常返回給傳送者。異常被包裝在一個 RemoteInvocationResult 物件中。在傳送者端,有一個可用的 RemoteInvocationAwareMessageConverterAdapter ,如果在 RabbitTemplate 中配置,則會重新丟擲伺服器端異常,並將其包裝在 AmqpRemoteException 中。伺服器異常的堆疊跟蹤是透過合併伺服器和客戶端的堆疊跟蹤合成的。

該機制通常只適用於預設的 SimpleMessageConverter ,它使用 Java 序列化。異常通常對“Jackson 不友好”,無法序列化為 JSON。如果你使用 JSON,可以考慮使用 errorHandler 來返回其他 Jackson 友好的 Error 物件,當異常丟擲時。
在版本 2.1 中,此介面從包 o.s.amqp.rabbit.listener 移動到 o.s.amqp.rabbit.listener.api

從版本 2.1.7 開始, Channel 在訊息頭中可用;這允許你在使用 AcknowledgeMode.MANUAL 時確認或拒絕(ack or nack)失敗的訊息。

public Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
          ListenerExecutionFailedException exception) {
              ...
              message.getHeaders().get(AmqpHeaders.CHANNEL, Channel.class)
                  .basicReject(message.getHeaders().get(AmqpHeaders.DELIVERY_TAG, Long.class),
                               true);
          }

從版本 2.2.18 開始,如果丟擲訊息轉換異常,錯誤處理器將被呼叫, message 引數中為 null 。這允許應用程式向呼叫者傳送一些結果,表明接收到格式錯誤的訊息。之前,這類錯誤會被丟擲並由容器處理。