【问题标题】:Spring boot stomp sends RECEIPT frame multiple timesSpring Boot stomp 多次发送 RECEIPT 帧
【发布时间】:2021-04-22 08:37:27
【问题描述】:

我正在 Spring Boot 上使用 Stomp 和 Rabbitmq 开发一个聊天应用程序。

当客户端向服务器发送消息(Spring Boot)时,服务器将消息保存到数据库中,然后将消息发送给其接收者。

我想做的是在客户发送消息时向他们发送带有message-idRECEIPT 帧,让他们知道他们的消息已保存到数据库中。

我可以从ExecutorChannelInterceptor 类的afterMessageHandled() 发送RECEIPT 帧。但它会多次发送相同的RECEIPT 帧,比如三次。

因此,对于一条消息,客户端会收到 3 次相同的 RECEIPT 帧。

这是我的ChannelInterceptor,它将消息保存到presend()的数据库中

public class StompChannelInterceptor implements ChannelInterceptor {

@Autowired
private ChatService chatService;

@Autowired
private CompositeMessageConverter compositeMessageConverter;


@Override
public Message<?> preSend(Message<?> message, @NonNull MessageChannel channel) {
    MessageHeaders messageHeaders = message.getHeaders();
    StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message);
    StompCommand stompCommand = stompHeaderAccessor.getCommand();

    if (StompCommand.SUBSCRIBE.equals(stompCommand)) {
        //validate subscribe
    } else if (StompCommand.SEND.equals(stompCommand)) {
        System.out.println("presend!!!!!!!!!!!!!!!!!!!");
        ChatMessageDTO chatMessageDTO =
                (ChatMessageDTO) compositeMessageConverter.fromMessage(message, ChatMessageDTO.class);
        chatService.validateAndSaveMessage(chatMessageDTO);
    }
    return message;
}
}

这是我的 MessageMapping 处理传入消息的函数

@MessageMapping("/chat/send")
public void send(@Payload ChatMessageDTO chatMessageDTO, MessageHeaders messageHeaders) {
    System.out.println("send!!!!!!!!!!!!!!!!!!!!!!!!!");
    simpMessagingTemplate.convertAndSend(queue, chatMessageDTO);
}

最后,这是我的ExecutorChannelInterceptor,它在afterMessageHandled() 中发送RECEIPT

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.interceptors(chatChannelInterceptor());

    registration.interceptors(new ExecutorChannelInterceptor() {

        @Override
        public void afterMessageHandled(Message<?> inMessage,
                                        MessageChannel inChannel, MessageHandler handler, Exception ex) {

            StompHeaderAccessor inAccessor = StompHeaderAccessor.wrap(inMessage);

            if (StompCommand.SEND.equals(inAccessor.getCommand())) {

                System.out.println("afterMessageHandled");

                if (outChannel != null) {
                    StompHeaderAccessor outAccessor = StompHeaderAccessor.create(StompCommand.RECEIPT);
                    outAccessor.setSessionId(inAccessor.getSessionId());
                    outAccessor.setReceiptId(receipt);
                    outAccessor.setLeaveMutable(true);
                    outAccessor.setMessageId(inAccessor.getMessageId());

                    Message<byte[]> outMessage =
                            MessageBuilder.createMessage(new byte[0], outAccessor.getMessageHeaders());

                    outChannel.send(outMessage);
                }
            }
        }
    });
}

如果我运行这段代码,我得到了这个日志,这表明afterMessageHandled()被调用了3次。

presend!!!!!!!!!!!!!!!!!!!
afterMessageHandled!!!!!!!!!!!!!!!!!!!!!
afterMessageHandled!!!!!!!!!!!!!!!!!!!!!
send!!!!!!!!!!!!!!!!!!!!!!!!!
afterMessageHandled!!!!!!!!!!!!!!!!!!!!!

所以,问题是

  1. 有什么方法可以在presend() 之后向客户发送一个 RECEIPT 帧仅一次,因为我想在确认消息已保存到数据库后发送 RECEIPT 帧发生在presend()

  2. 是否可以更改presend() 中的有效负载或标头?

【问题讨论】:

    标签: spring-boot websocket rabbitmq stomp


    【解决方案1】:

    我发现对 afterHanldedMessage() 的每次调用都带有不同的处理程序。所以你可以根据不同的处理程序做你想做的事。你可能想做 If(handler instanceof SomeHandlerClass)。

    【讨论】:

      猜你喜欢
      • 2018-02-21
      • 1970-01-01
      • 2016-05-06
      • 2020-06-17
      • 2014-02-14
      • 1970-01-01
      • 2017-01-31
      • 2018-08-28
      • 2020-10-31
      相关资源
      最近更新 更多