当Spring JMS 发生异常时停止在队列的消费者中一次又一次地接收消息

Stop receiving again and again messages in consumer of the queue when an exception occurs in Spring JMS

我从发件人应用程序发送消息如下。

    @GetMapping("send/event")
    public void sendEvent() {
        try {
            String stringEvent = objectMapper.writeValueAsString(getEvent());
            jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
            jmsTemplate.setSessionTransacted(false);
            jmsTemplate.convertAndSend(SEND_QUEUE_NAME, stringEvent);
        } catch (JmsException | JsonProcessingException e) {
            e.printStackTrace();
        }
    }

并且在接收方应用程序中,我收到如下消息。

    @Override
    @JmsListener(destination = "${mq.receive_queue}")
    public void receive(Message message) {
        try {
            String jsonEvent = ((TextMessage) message).getText();
            Event event = objectMapper.readValue(jsonEvent, Event.class);
            System.out.println(event.toString());
            message.acknowledge();
            validateEventRequest(event);
        } catch (JMSException | IOException e) {
            e.printStackTrace();
        }
    }

主要问题是 validateEventRequest(event); 调用时。因为在这个方法中,我有几个服务和场景可能会引发异常。我不希望抛出异常时,消息回滚到队列并再次接收。我只想在发生异常时完全消费消息。 因此,我将这些行添加到发件人应用程序中。

  jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
  jmsTemplate.setSessionTransacted(false);

但没有任何变化。如果有人对此有想法,我将不胜感激。

附加信息
我在接收器应用程序的接收方法中调用了这些

int deliveryMode = jmsTemplate.getDeliveryMode(); -->2
int sessionAcknowledgeMode = jmsTemplate.getSessionAcknowledgeMode(); -->1
int jmsDeliveryMode = message.getJMSDeliveryMode(); -->2
boolean jmsRedelivered = message.getJMSRedelivered(); -->true

很可能您的 validateEventRequest(event) 抛出了 JMSExceptionIOException(或其子类之一)以外的东西,这意味着 [=15] 中的 catch =] 将 而不是 实际捕获它。我相信当此异常从您的 receive 方法中抛出时,将触发消息的重新传递。我建议您改用更通用的 Exception,例如:

@Override
@JmsListener(destination = "${mq.receive_queue}")
public void receive(Message message) {
    try {
        String jsonEvent = ((TextMessage) message).getText();
        Event event = objectMapper.readValue(jsonEvent, Event.class);
        System.out.println(event.toString());
        message.acknowledge();
        validateEventRequest(event);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

此外,值得注意的是,更改消息的发送方式不会影响消息的接收方式。如果您想更改消息的接收方式,则需要更改接收方应用程序。