異常處理
預設情況下,如果帶註解的監聽器方法丟擲異常,異常會被拋給容器,並且訊息會被重新入隊並重新投遞、丟棄或路由到死信交換器,具體取決於容器和經紀商的配置。傳送者不會收到任何返回。
從版本 2.0 開始,該 @RabbitListener
註解有兩個新屬性:errorHandler
和 returnExceptions
。
這些屬性預設未配置。
你可以使用 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
。這允許應用程式向呼叫者傳送一些結果,表明接收到格式錯誤的訊息。之前,這類錯誤會被丟擲並由容器處理。