Exception Spring AMQP RPC使用者并引发异常
我有一个处于RPC模式的使用者(RabbitListner),我想知道是否有可能抛出可由发布者处理的异常 为了更清楚地说明,我的解释如下:Exception Spring AMQP RPC使用者并引发异常,exception,rabbitmq,spring-amqp,Exception,Rabbitmq,Spring Amqp,我有一个处于RPC模式的使用者(RabbitListner),我想知道是否有可能抛出可由发布者处理的异常 为了更清楚地说明,我的解释如下: 发布服务器以RPC模式发送消息 消费者收到消息,检查消息的有效性,如果由于缺少参数而无法统计消息,则我想抛出异常。异常可以是特定的业务异常,也可以是特定的AmqpException,但我希望发布者可以在未进入超时时处理此异常 我尝试使用AmqpRejectAndDontRequeueException,但我的发布者没有收到异常,只是收到一个空响应 这样做
- 发布服务器以RPC模式发送消息
- 消费者收到消息,检查消息的有效性,如果由于缺少参数而无法统计消息,则我想抛出异常。异常可以是特定的业务异常,也可以是特定的AmqpException,但我希望发布者可以在未进入超时时处理此异常
@Configuration
public class RabbitErrorHandler implements RabbitListenerErrorHandler {
@Override public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) {
throw e;
}
}
@Override
@RabbitListener(queues = "${rabbit.queue}"
, errorHandler = "rabbitErrorHandler"
, returnExceptions = "true")
public ReturnObject receiveMessage(Message message) {
rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
当消息受到使用者的威胁,但它发送了一个错误时,我获得一个RemoteInvocationResult,其中包含e.getCause().getCause()中的原始异常。您必须将消息作为错误返回,使用者应用程序可以选择将其视为异常。但是,我认为正常的异常处理流不适用于消息传递。您的发布应用程序(RPC服务的使用者)需要知道可能出现的问题,并对其进行编程以处理这些可能性 请参见
@RabbitListener
(自2.0版起)上的returnExceptions
属性
returnExceptions
属性,当true
时,将导致异常返回给发送方。异常被包装在RemoteInvocationResult
对象中
在发送方端,有一个可用的RemoteInvocationAwareMessageConverterAdapter
,如果配置到rabbitemplate
,它将重新抛出服务器端异常,并封装在amqpmoteexception
中。服务器异常的堆栈跟踪将通过合并服务器和客户端堆栈跟踪来合成
重要
这种机制通常只适用于默认的SimpleMessageConverter,它使用Java序列化;异常通常不“Jackson友好”,因此无法序列化为JSON。如果使用JSON,请考虑使用Error Healthor在抛出异常时返回其他杰克逊友好的错误对象。
如果使用java序列化,则可以将异常配置为传播到客户端,然后在客户端重新抛出异常。看看我的答案。@GaryRussell-这是一个很好的答案。我仍然认为“例外”是为那些不能正常工作的代码保留的,而不是服务故障,服务故障的边界通常定义得更好,应该编程处理所有非正常条件,作为一流的代码。这是应社区的要求添加的,但我同意最好设置一些协议,将有意义的错误返回给发送方,避免这种紧密耦合。谢谢您的回复。最后,我决定像@GaryRussell一样求婚。你的回答也很有趣,让我知道即使这样,这也不是一个坏习惯。谢谢你的回答。也感谢与玩家的讨论。最后,我决定使用错误处理程序来实现您所建议的。最初,我是按照玩家的建议来做的,但是有异常更安全,如果我没有捕获到所有的异常,处理程序将确保不会丢失异常。也许我会把我的一些代码放在我的问题中,因为我发现这不是很容易(我是SpringAMQP新手),所以我花了一些时间来找到一种方法,也许这不是正确的方法。谢谢你,现在我明白了你对那些对杰克逊不友好的例外所说的话的意思。在我将rabbit模板与SimpleMessageConverter一起使用之前,它序列化了我的java对象,但现在我想将其用作JSON。因此,如果我想使用Jackson转换器,我可以只使用新的RemoteInvocationAwareMessageConverterAdapter(新的Jackson2JsonMessageConverter())。你能告诉我怎么做吗?不,没那么简单;如上所述;您需要在服务器端进行更改以捕获异常并返回一些特殊的错误对象;然后,您必须在客户端解释该错误对象,才能将其作为异常抛出。谢谢。我已经执行了你的建议。我从RabbitErrorHandler创建了一个在错误情况下返回的自定义对象。
@Override
@RabbitListener(queues = "${rabbit.queue}"
, errorHandler = "rabbitErrorHandler"
, returnExceptions = "true")
public ReturnObject receiveMessage(Message message) {
rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());