处理异常
默认情况下,如果已注解的监听器方法抛出异常,该异常将被抛回容器,消息将被重新入队、重新投递、丢弃或路由到死信交换,具体取决于容器和代理的配置。发送方不会收到任何返回结果。
从版本 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 消息 Message<?> 对象,以及监听器抛出的异常(被封装在 ListenerExecutionFailedException 中)。
错误处理器既可以返回某些结果(该结果将作为回复发送),也可以抛出原始异常或新的异常(该异常将根据 returnExceptions 的设置被抛给容器或返回给发送方)。
当 returnExceptions 属性值为 true 时,会导致异常被返回给发送方。
该异常会被封装在 RemoteInvocationResult 对象中。
在发送方一侧,存在一个可用的 RemoteInvocationAwareMessageConverterAdapter,若将其配置到 RabbitTemplate 中,则会重新抛出服务器端的异常,该异常被封装在 AmqpRemoteException 中。
服务器端异常的堆栈跟踪信息通过合并服务器端与客户端的堆栈跟踪信息生成。
此机制通常仅与默认的 SimpleMessageConverter 配合使用,该默认值采用 Java 序列化方式。异常通常不兼容 Jackson(即“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)或否定确认(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 开始,如果发生消息转换异常,将调用错误处理器,并在 null 的 message 参数中传入该值。这允许应用程序向调用方发送某些结果,以表明已接收到格式不良的消息。此前,此类错误由容器抛出并处理。