Exception Spring AMQP RPC使用者并引发异常

Exception Spring AMQP RPC使用者并引发异常,exception,rabbitmq,spring-amqp,Exception,Rabbitmq,Spring Amqp,我有一个处于RPC模式的使用者(RabbitListner),我想知道是否有可能抛出可由发布者处理的异常 为了更清楚地说明,我的解释如下: 发布服务器以RPC模式发送消息 消费者收到消息,检查消息的有效性,如果由于缺少参数而无法统计消息,则我想抛出异常。异常可以是特定的业务异常,也可以是特定的AmqpException,但我希望发布者可以在未进入超时时处理此异常 我尝试使用AmqpRejectAndDontRequeueException,但我的发布者没有收到异常,只是收到一个空响应 这样做

我有一个处于RPC模式的使用者(RabbitListner),我想知道是否有可能抛出可由发布者处理的异常

为了更清楚地说明,我的解释如下:

  • 发布服务器以RPC模式发送消息
  • 消费者收到消息,检查消息的有效性,如果由于缺少参数而无法统计消息,则我想抛出异常。异常可以是特定的业务异常,也可以是特定的AmqpException,但我希望发布者可以在未进入超时时处理此异常
我尝试使用AmqpRejectAndDontRequeueException,但我的发布者没有收到异常,只是收到一个空响应

这样做是可能的,还是不是一个好的实践

编辑1:

@GaryRussel回复后,我的问题就解决了:

  • 对于RabbitListner,我创建了一个错误处理程序:

     @Configuration
     public class RabbitErrorHandler implements         RabbitListenerErrorHandler {
     @Override public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) {
    throw e;
    }
    
    }

  • 使用参数创建@RabbitListner,其中rabbitErrorHandler是我之前定义的bean:

    @Override
    @RabbitListener(queues = "${rabbit.queue}"
        , errorHandler = "rabbitErrorHandler"
        , returnExceptions = "true")
     public ReturnObject receiveMessage(Message message) {
    
  • 对于RabbitTemplate,我设置了以下属性:

       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());