处理异常

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

从 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时确认或拒绝失败的消息

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