首页 > 解决方案 > RabbitHandler:如何正确捕获“ListenerExecutionFailedException:侦听器方法'不匹配'抛出异常”并继续工作

问题描述

对于一个应用程序,我正在使用 Spring Boot 和 RabbitMQ 进行一些测试。我设置了一个非常简单的 Sender - Receiver 应用程序: Sender:

public class Tut1Sender
{
    private final Gson gson = new Gson();

    @Autowired
    private RabbitTemplate template;

    @Autowired
    private Queue queue;

    public static int count = 1;

    @Scheduled(fixedDelay = 1000, initialDelay = 500)
    public void send() throws InterruptedException
    {
        String message = "Hello World! "+" Nr. "+count;
        MessageObject mo = new MessageObject(message);
        String toJson = gson.toJson(mo);
        this.template.convertAndSend(queue.getName(), toJson);
        System.out.println(" [x] Sent '" + toJson + "'");
        Thread.sleep(5);
        count++;
    }
}

这部分工作得很好,并用消息填充我的队列。

这是我的接收器:

@RabbitListener(queues = "hello")
public class Tut1Receiver
{

    private final Gson gson = new Gson();

    @RabbitHandler
    public void receive(String in) throws InterruptedException
    {
        System.out.println("Received Raw: " + in);
        MessageObject fromJson = gson.fromJson(in, MessageObject.class);

        System.out.println("Received Message '" + fromJson + "'");
        int nextInt = ThreadLocalRandom.current().nextInt(1000, 5000);
        System.out.println("Sleep for " + nextInt + " ms");
        Thread.sleep(nextInt);
    }
}

发送者创建的消息由接收者正确处理。我得到了一个很好的输出,消息被确认并从队列中删除。

然后我通过 RabbitMQ 的 Web-GUI 将消息直接放入队列中。

发件人获取此消息。我可以这样说是因为我创建的消息从状态“Ready”切换到“Unacked”(如 Web-GUI 中所示)发件人没有给我任何输出。

然后我配置了ContainerFactory:

@Profile("receiver")
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer,
            ConnectionFactory connectionFactory)
    {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setErrorHandler(e -> {
            System.out.println("Error: "+e);
            System.out.println("Raw: "+((ListenerExecutionFailedException) e).getFailedMessage().toString());

        });
        return factory;
    }

现在我收到以下错误(在无限循环中)

Error: org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'no match' threw exception
Raw: (Body:'[B@53452feb(byte[11])' MessageProperties [headers={content_type=text/plain, content_encoding=UTF-8}, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=true, receivedExchange=, receivedRoutingKey=hello, deliveryTag=1, consumerTag=NOT_SET, consumerQueue=hello])

我该如何处理这个错误?发件人应该只显示错误,确认消息并继续处理下一条消息。

一般来说,处理错误消息的正确方法是什么?

标签: javaspring-bootrabbitmq

解决方案


对于破碎的消息,消费者可以rejectdeliver该消息。如果您确定任何其他消费者无法处理损坏的消息,您应该告诉代理丢弃该消息或将其传递到死信交换。

spring amqp 的官方文档中,我发现:

另一种选择是将容器的rejectRequeued 属性设置为false。这会导致丢弃所有失败的消息。当使用 RabbitMQ 2.8.x 或更高版本时,这也有助于将消息传递到死信交换。

或者,您可以抛出 AmqpRejectAndDontRequeueException;这可以防止消息重新排队,无论 rejectRequeued 属性的设置如何。


推荐阅读