SpringAMQP errorHandler和returnExceptions问题

时间:2018-12-19 07:16:54

标签: spring-amqp

我不确定我对errorHandler和returnExceptions的理解是否正确。

但这是我的目标:我从App_A发送了一条消息,使用@RabbitListener接收App_B中的消息。

根据文档 https://docs.spring.io/spring-amqp/docs/2.1.3.BUILD-SNAPSHOT/reference/html/_reference.html#annotation-error-handling

我假设APP_B在处理消息期间是否有业务异常,可以通过@RabbitListener上正确的方式通过设置errorHandler和returnExceptions来使异常返回到App_A。

我理解正确吗?

如果我很严厉,如何正确使用它?

使用我的代码,我在APP_A中什么也没得到。

这是我在APP_B中的代码

errorHandler:

@Component(value = "errorHandler")
public class ErrorHandler implements RabbitListenerErrorHandler {

    @Override
    public Object handleError(Message arg0, org.springframework.messaging.Message<?> arg1,
            ListenerExecutionFailedException arg2) throws ListenerExecutionFailedException {
        throw new ListenerExecutionFailedException("msg", arg2, null);
    }

}

RabbitListener:

@RabbitListener(
        bindings = @QueueBinding(
            value = @Queue(value = "MRO.updateBaseInfo.queue", durable = "true"),
            exchange = @Exchange(name = "MRO_Exchange", type = ExchangeTypes.DIRECT, durable = "true"),
            key = "baseInfoUpdate"
        ),
//      errorHandler = "errorHandler",
        returnExceptions = "true"
    )
    public void receiveLocationChangeMessage(String message){
        BaseUpdateMessage newBaseInfo = JSON.parseObject(message, BaseUpdateMessage.class);
        dao.upDateBaseInfo(newBaseInfo);
    }

和APP_A中的代码

@Component
public class MessageSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void editBaseInfo(BaseUpdateMessage message)throws Exception {
        //and i am not sure set RemoteInvocationAwareMessageConverterAdapter in this way is right 
        rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());

        rabbitTemplate.convertAndSend("MRO_Exchange", "baseInfoUpdate", JSON.toJSONString(message));
    }

}

我对三点很困惑:

1)我必须同时使用errorHandler和returnExceptions吗?我以为errorHandler就像一个后处理器,可以让我自定义异常。如果我不需要自定义异常,我可以只在没有errorHandler的情况下设置returnExceptions吗?

2)用@RabbitListener注释的方法是否应该返回某些内容,否则void可以吗?

3)在发送方(我的情况是APP_A),是否有任何特定的配置来捕获异常?

我的工作区环境:

Spring boot 2.1.0

码头上的

rabbitMQ服务器3.7.8

1 个答案:

答案 0 :(得分:0)

1)不,除非您想增强异常,否则不需要en错误处理程序。

2)如果该方法返回void;发送者将最终等待超时,以防永远不会到达的答复,以防万一可能引发异常。那可能不是很好地利用资源。最好总是发送答复,以释放发布者一方。

3)仅RemoteInvocationAwareMessageConverterAdapter

这是一个例子:

@SpringBootApplication
public class So53846303Application {

    public static void main(String[] args) {
        SpringApplication.run(So53846303Application.class, args);
    }

    @RabbitListener(queues = "foo", returnExceptions = "true")
    public String listen(String in) {
        throw new RuntimeException("foo");
    }

    @Bean
    public ApplicationRunner runner(RabbitTemplate template) {
        template.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
        return args -> {
            try {
                template.convertSendAndReceive("foo", "bar");
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        };
    }

}

org.springframework.amqp.AmqpRemoteException: java.lang.RuntimeException: foo
    at org.springframework.amqp.support.converter.RemoteInvocationAwareMessageConverterAdapter.fromMessage(RemoteInvocationAwareMessageConverterAdapter.java:74)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1500)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1433)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1425)
    at com.example.So53846303Application.lambda$0(So53846303Application.java:28)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:794)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
    at com.example.So53846303Application.main(So53846303Application.java:15)
Caused by: java.lang.RuntimeException: foo
    at com.example.So53846303Application.listen(So53846303Application.java:20)

如您所见,存在一个本地org.springframework.amqp.AmqpRemoteException,其原因是远程服务器上抛出了实际的异常。