异常处理

默认情况下,如果带注解的监听器方法抛出异常,异常会被抛给容器,并且消息会被重新入队并重新投递、丢弃或路由到死信交换器,具体取决于容器和经纪商的配置。发送者不会收到任何返回。

从版本 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 。这允许应用程序向调用者发送一些结果,表明接收到格式错误的消息。之前,这类错误会被抛出并由容器处理。