跳到主要内容

处理异常

DeepSeek V3 中英对照 Handling Exceptions

默认情况下,如果带注解的监听器方法抛出异常,异常会被抛给容器,并且消息会根据容器和代理的配置进行重新排队和重新投递、丢弃或路由到死信交换器。不会向发送者返回任何内容。

从版本 2.0 开始,@RabbitListener 注解新增了两个属性:errorHandlerreturnExceptions

默认情况下,这些内容未进行配置。

你可以使用 errorHandler 来提供一个 RabbitListenerErrorHandler 实现的 bean 名称。这个函数式接口有一个方法,如下所示:

@FunctionalInterface
public interface RabbitListenerErrorHandler {

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

}
java

如你所见,你可以访问从容器接收到的原始消息、由消息转换器生成的 spring-messaging Message<?> 对象,以及监听器抛出的异常(包装在 ListenerExecutionFailedException 中)。错误处理器可以返回一些结果(作为回复发送),或者抛出原始或新的异常(根据 returnExceptions 设置,异常将抛出到容器或返回给发送者)。

returnExceptions 属性,当设置为 true 时,会导致异常被返回给发送方。异常被包装在一个 RemoteInvocationResult 对象中。在发送方一侧,有一个可用的 RemoteInvocationAwareMessageConverterAdapter,如果将其配置到 RabbitTemplate 中,它会重新抛出服务器端的异常,该异常被包装在一个 AmqpRemoteException 中。服务器异常的堆栈跟踪通过合并服务器和客户端的堆栈跟踪来合成。

important

此机制通常仅适用于默认的 SimpleMessageConverter,它使用 Java 序列化。异常通常不是“Jackson 友好”的,无法序列化为 JSON。如果你使用 JSON,请考虑在抛出异常时使用 errorHandler 返回一些其他 Jackson 友好的 Error 对象。

important

在 2.1 版本中,此接口从包 o.s.amqp.rabbit.listener 移至 o.s.amqp.rabbit.listener.api

从 2.1.7 版本开始,Channel 可以在消息头中获取;这允许你在使用 AcknowledgeMode.MANUAL 时确认或拒绝失败的消息:

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);
}
java

从 2.2.18 版本开始,如果抛出消息转换异常,将调用错误处理程序,并在 message 参数中传入 null。这允许应用程序向调用方发送一些结果,表明收到了格式错误的消息。在此之前,此类错误会被抛出并由容器处理。