处理异常
默认情况下,如果带注解的监听器方法抛出异常,异常会被抛给容器,并且消息会根据容器和代理的配置进行重新排队和重新投递、丢弃或路由到死信交换器。不会向发送者返回任何内容。
从版本 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
。这允许应用程序向调用方发送一些结果,表明收到了格式错误的消息。在此之前,此类错误会被抛出并由容器处理。