Spring Boot stomp 多次发送 RECEIPT 帧

问题描述

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

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

我想做的是在客户端发送消息时向客户端发送一个带有 function test(){ var ss = SpreadsheetApp.getActiveSpreadsheet(); var ws = ss.getSheetByName("SalesPlan"); const lastData = ws.getRange(2,1,6).getValues(); WeeklySalesPlan(lastData) } function WeeklySalesPlan(lastData){ //Debemos validar de que es un nuevo registro sin procesar var ss = SpreadsheetApp.getActiveSpreadsheet(); var ws = ss.getSheetByName("SalesPlan"); if(lastData[0][5] == "Unprocessed"){ //Debemos capturar todos los open deals que existen al momento var ss = SpreadsheetApp.getActiveSpreadsheet(); var activeSheet = ss.getSheetByName("SalesPlanWeekly"); var dateFrom = new Date(lastData[0][1]); var dateto = new Date(lastData[0][2]); Logger.log('dateFrom :' + dateFrom) var salesPlan_MonthFrom = dateFrom.getMonth(); Logger.log("salesPlan_MonthTo: " + salesPlan_MonthTo); var salesPlan_YearFrom = dateFrom.getYear(); Logger.log("salesPlan_YearFrom: " + salesPlan_YearFrom); var salesPlan_Product = lastData[0][3]; var salesPlan_Quantity = lastData[0][4]; for(var i = 0; i < 31; i++){ var e = new Date(salesPlan_YearFrom,salesPlan_MonthFrom,i + 1,0); var day = e.getDay(); var firstWeekBegin = 1; if(day == 1){ break; }else{ firstWeekBegin = firstWeekBegin + 1; } } var firstWeekDate = new Date(salesPlan_YearFrom,firstWeekBegin,0); Logger.log("firstWeekDate: " + firstWeekDate); } } RECEIPT 帧,让他们知道他们的消息已保存到数据库中。

我可以从 message-id 类的 RECEIPT 发送 afterMessageHandled() 帧。但它多次发送相同的 ExecutorChannelInterceptor 帧,例如 3 次。

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

这是我的 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

中发送 RECEIPT
afterMessageHandled()

如果我运行这段代码,我会得到这个日志,它表明 @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); } } } }); } 调用了 3 次。

afterMessageHandled()

所以,问题是

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

  2. 请问可以更改 presend() 中的负载或标头吗?

解决方法

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