无法使用 Spring Boot Websocket Stomp 向用户发送直接消息

问题描述 投票:0回答:0

我有一个在 Spring Boot 3 中实现的客户端服务器应用程序。它使用带有 stomp 的 web 套接字相互通信。目前服务端和客户端都是使用不同版本的 Spring 和 Spring Boot 实现的。

我成功地互相发送了使用共同主题的消息。消息被加密,因此只有目标客户才能解密和查看它。

该应用程序旨在用于更复杂的目的,但出于我的目的,让我将其作为聊天应用程序呈现给您。

这是测试功能的代码的一部分: @Autowired 私人 SimpMessagingTemplate simpMessagingTemplate;

@Autowired
private ActiveUserStore activeUserStore;

@MessageMapping("/send")
@SendToUser("/queue/chat")
public void sendToUser(@Payload WsIncomingMessage wsIncomingMessage, Principal user, @Header("simpSessionId") String sessionId) {
    log.info(" /queue/chat > incoming msg: {}, user: {}, header: {}", wsIncomingMessage, user, sessionId);
    WsOutgoingMessage wsOutgoingMessage = new WsOutgoingMessage();
    wsOutgoingMessage.setMessage(wsIncomingMessage.getMessage());
    wsOutgoingMessage.setMessageType(wsIncomingMessage.getMessageType());
    wsOutgoingMessage.setSentDatetime(wsIncomingMessage.getSentDatetime());
    wsOutgoingMessage.setSource(wsIncomingMessage.getSource());
    wsOutgoingMessage.setDestination(wsIncomingMessage.getDestination());
    wsIncomingMessage.setAdId(wsIncomingMessage.getAdId());
    log.info(" /queue/chat > outgoing msg: {}, user: {}, header: {}", wsIncomingMessage, user, sessionId);
    
    simpMessagingTemplate.convertAndSendToUser(activeUserStore.getUser(wsOutgoingMessage.getDestination()).getPrincipal(), "/queue/chat", wsOutgoingMessage);
}

Calling

activeUserStore.getUser(wsOutgoingMessage.getDestination()).getPrincipal()
返回识别用户的电话号码。我们认为完整路径中的电话号码可以唯一标识用户。

我的握手:

@Slf4j
public class CustomHandshakeHandler extends DefaultHandshakeHandler { 

    
    @Override
    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
            Map<String, Object> attributes) {
        String uuid = UUID.randomUUID().toString();
        Principal pinciplal = request.getPrincipal();

        if (pinciplal instanceof UsernamePasswordAuthenticationToken) {
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) pinciplal;
            Object principalObj = usernamePasswordAuthenticationToken.getPrincipal();
            if (principalObj instanceof JwtUserDetails) {
                JwtUserDetails connectingUser = (JwtUserDetails) principalObj;
                connectingUser.setSessionUuid(uuid);
                
            }
        }
        log.info("principal in CustomHandshakeHandler: {}", pinciplal);
        return pinciplal;
    }
}

校长的字符串表示:

UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]]

Spring Boot 服务器正在接收 stomp 消息。我认为它也在返回消息,但我不知道如何记录返回的消息:

[boundChannel-13][0;39m [36mc.l.c.f.k.c.controller.ChatController   [0;39m [2m:[0;39m  /queue/chat > incoming msg: WsIncomingMessage(message=Hi, messageType=text/plain, destination=4, sentDatetime=2023-04-29T10:39:49+07:00, source=3, sourceImage=0, adId=no-ad), user: UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], header: 36d934da-79d7-f00b-6459-331f1cef60ca

[boundChannel-13][0;39m [36mc.l.c.f.k.c.controller.ChatController   [0;39m [2m:[0;39m  /queue/chat > outgoing msg: WsIncomingMessage(message=Hi, messageType=text/plain, destination=4, sentDatetime=2023-04-29T10:39:49+07:00, source=3, sourceImage=0, adId=no-ad), user: UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], header: 36d934da-79d7-f00b-6459-331f1cef60ca

服务器正在注册订阅事件:

event: SessionSubscribeEvent[GenericMessage [payload=byte[0], headers={simpMessageType=SUBSCRIBE, stompCommand=SUBSCRIBE, nativeHeaders={destination=[/user/queue/chat], id=[0]}, simpSessionAttributes={}, simpHeartbeat=[J@197209d9, simpSubscriptionId=0, simpUser=UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], simpSessionId=36d934da-79d7-f00b-6459-331f1cef60ca, simpDestination=/user/queue/chat}]]

客户端也可以看到订阅成功:

StompSession.Subscription messageSubscriberSubscription = sessionStomp.get().subscribe("/user/queue/chat", messageSubscriber);
log.info("messageSubscriberSubscription: {}", messageSubscriberSubscription);

10:39:43.244 [Grizzly(2)] INFO com.lomatechnology.cambodia.fintech.kke.chat.web.ServerCommunication -- messageSubscriberSubscription: Subscription [id=0, destination='/user/queue/chat', receiptId='null', handler=com.lomatechnology.cambodia.fintech.kke.chat.web.MessageSubscriber@39fe1782]
10:39:49.022 [AWT-EventQueue-0] INFO com.lomatechnology.cambodia.fintech.kke.chat.util.DatetimeUtil -- Returned date string: 2023-04-29T10:39:49+07:00
10:39:49.022 [AWT-EventQueue-0] INFO com.lomatechnology.cambodia.fintech.kke.chat.ui.ChatGui -- About to send: WsOutgoingMessage(message=Hi, messageType=text/plain, destination=4, sourceImage=null, sentDatetime=2023-04-29T10:39:49+07:00, source=3, adId=no-ad)

唯一的问题是预期的客户端永远不会收到消息。是

simpMessagingTemplate.convertAndSendToUser
中原则的错误使用还是我错过了什么?

java spring-boot stomp spring-websocket
© www.soinside.com 2019 - 2024. All rights reserved.