Handling Exceptions

默认情况下,如果带注释的侦听器方法抛出异常,它将被抛出到容器中,并且根据容器和代理配置,消息将重新排队并重新发送、丢弃或路由到无效字母交换。没有任何东西返回给发送方。

从版本 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 消息传递`Message<?>`对象以及侦听器抛出的异常(包装在`ListenerExecutionFailedException`中)。错误处理程序可以返回一些结果(作为回复发送)或抛出原始异常或新异常(根据`returnExceptions`设置抛出到容器或返回给发送者)。

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

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

在版本 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);
          }

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