异常处理

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

从 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` 时确认或否定失败的消息。

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`。这允许应用程序向调用方发送某些结果,指示已收到格式错误的消息。以前,此类错误由容器抛出和处理。