异常处理
默认情况下,如果一个带注解的监听器方法抛出异常,该异常会被抛给容器,消息会根据容器和代理的配置重新入队、重新投递、丢弃或路由到死信交换机。不会向发送方返回任何内容。
从 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 中。服务器异常的堆栈跟踪通过合并服务器和客户端堆栈跟踪来合成。
此机制通常只适用于使用 Java 序列化的默认 SimpleMessageConverter。异常通常不“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。这允许应用程序向调用方发送一些结果,指示收到了格式错误的消息。以前,此类错误由容器抛出和处理。