我有一个在 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
中原则的错误使用还是我错过了什么?