此版本仍在开发中,目前尚不稳定。如需最新稳定版本,请使用 Spring AMQP 4.0.2spring-doc.cadn.net.cn

异常处理

许多与 RabbitMQ Java 客户端相关的操作都可能抛出受检异常。例如,存在大量可能抛出 IOException 实例的情况。Spring AMQP 的 RabbitTemplateSimpleMessageListenerContainer 及其他组件会捕获这些异常,并将其转换为 AmqpException 层次结构中的一种异常。这些异常在 org.springframework.amqp 包中定义,而 AmqpException 则是该层次结构的基类。spring-doc.cadn.net.cn

当监听器抛出异常时,它会被包装在 ListenerExecutionFailedException 中。通常,消息会被代理拒绝并重新入队。将 defaultRequeueRejected 设置为 false 会导致消息被丢弃(或路由至死信交换机)。正如在 消息监听器与异步情况 中所讨论的那样,监听器可以抛出 AmqpRejectAndDontRequeueException(或 ImmediateRequeueAmqpException)以有条件地控制此行为。spring-doc.cadn.net.cn

然而,存在一类错误,其中监听器无法控制其行为。当遇到无法转换的消息时(例如,无效的 content_encoding 头部),某些异常会在消息到达用户代码之前被抛出。当 defaultRequeueRejected 设置为 true(默认值)(或抛出 ImmediateRequeueAmqpException)时,此类消息将反复重新投递。在 1.3.2 版本之前,用户需要编写自定义的 ErrorHandler(如 异常处理 中所讨论),以避免此情况。spring-doc.cadn.net.cn

从版本 1.3.2 开始,默认的 ErrorHandler 现在已更改为 ConditionalRejectingErrorHandler,该值会拒绝(且不会重新入队)因不可恢复错误而失败的消息。具体而言,它会拒绝以下列错误失败的消息:spring-doc.cadn.net.cn

  • o.s.amqp…​MessageConversionException: 在使用 MessageConverter 将传入消息负载转换时可能抛出的异常。spring-doc.cadn.net.cn

  • o.s.messaging…​MessageConversionException: 当映射到 @RabbitListener 方法时,如果需要额外的转换,转换服务可能会抛出此异常。spring-doc.cadn.net.cn

  • o.s.messaging…​MethodArgumentNotValidException: 如果在监听器中使用了验证(例如,@Valid),而验证失败时可能会抛出此异常。spring-doc.cadn.net.cn

  • o.s.messaging…​MethodArgumentTypeMismatchException: 如果入站消息被转换为不适用于目标方法的类型,则可能抛出此异常。例如,参数声明为 Message<Foo>,但接收到的是 Message<Bar>spring-doc.cadn.net.cn

  • java.lang.NoSuchMethodException: 已在版本 1.6.3 中添加。spring-doc.cadn.net.cn

  • java.lang.ClassCastException: 已在版本 1.6.3 中添加。spring-doc.cadn.net.cn

您可以将此错误处理器配置为一个 FatalExceptionStrategy,以便用户能够提供自己的规则来有条件地拒绝消息——例如,Spring Retry 中的 BinaryExceptionClassifier 的委托实现(消息监听器与异步情况)。
此外,ListenerExecutionFailedException 现在具有一个 failedMessage 属性,您可以在决策中使用它。
如果 FatalExceptionStrategy.isFatal() 方法返回 true,错误处理器将抛出一个 AmqpRejectAndDontRequeueException
默认的 FatalExceptionStrategy 在确定异常为致命时会记录一条警告消息。spring-doc.cadn.net.cn

自版本 1.6.3 起,一种便捷的方式是通过继承 ConditionalRejectingErrorHandler.DefaultExceptionStrategy 并重写 isUserCauseFatal(Throwable cause) 方法,使其对致命异常返回 true,从而将用户自定义异常添加到致命列表中。spring-doc.cadn.net.cn

处理死信队列(DLQ)消息的一种常见模式是,对这些消息设置 time-to-live,同时配置额外的 DLQ 参数,使得这些消息过期后被重新路由回主队列以进行重试。这种技术的问题在于,导致致命异常的消息会无限循环。从版本 2.1 开始,ConditionalRejectingErrorHandler 会检测到消息中包含一个导致致命异常抛出的 x-death 头部信息。随后该消息会被记录并丢弃。您可以通过将 discardFatalsWithXDeath 属性设置在 ConditionalRejectingErrorHandler 上为 false 来恢复到之前的处理行为。spring-doc.cadn.net.cn

从版本 2.1.9 开始,包含这些致命异常的消息将被拒绝,并且默认情况下不会重新入队(即使容器确认模式为 MANUAL)。这些异常通常发生在监听器被调用之前,因此监听器没有机会对消息进行确认(ack)或否定确认(nack),导致消息仍以未确认状态保留在队列中。若要恢复到以前的行为,请将 rejectManual 属性在 ConditionalRejectingErrorHandler 上设置为 false