Spring Boot 未收到目标会话的Java STOMP消息

ghg1uchk  于 2024-01-06  发布在  Spring
关注(0)|答案(2)|浏览(307)

我试图实现一个简单的应用程序,未经身份验证的用户可以只在一个组名和发送消息组类型。
Config

  1. @Configuration
  2. @EnableWebSocketMessageBroker
  3. public class WebSockConfig implements WebSocketMessageBrokerConfigurer {
  4. @Override
  5. public void registerStompEndpoints(StompEndpointRegistry registry) {
  6. registry.addEndpoint("/ws-reg").withSockJS();
  7. }
  8. @Override
  9. public void configureMessageBroker(MessageBrokerRegistry config) {
  10. config.setApplicationDestinationPrefixes("/app");
  11. config.enableSimpleBroker("/all","/personal");
  12. }
  13. }

字符串
控制器

  1. @Controller
  2. public class HomeController {
  3. @Autowired
  4. private SimpMessagingTemplate simpMessagingTemplate;
  5. private final Map<String, List<String>> groupSessions = new HashMap<>();
  6. @MessageMapping("/group/{groupName}/join")
  7. public void joinGroup(@DestinationVariable String groupName, SimpMessageHeaderAccessor headerAccessor) {
  8. groupSessions.computeIfAbsent(groupName, k -> new ArrayList<>()).add(headerAccessor.getSessionId());
  9. }
  10. @MessageMapping("/group/{groupName}/send")
  11. public void sendToGroup(@DestinationVariable String groupName, Message<String> message) throws IOException {
  12. for ( String session : groupSessions.get(groupName)){
  13. simpMessagingTemplate.convertAndSendToUser(session,"/personal",message.getPayload());
  14. }
  15. }
  16. }


HTML中的JavaScript

  1. <script>
  2. const socket = new SockJS('http://localhost:8080/ws-reg');
  3. const stompClient = Stomp.over(socket);
  4. function joinGroup() {
  5. const groupName = document.getElementById('groupInput').value;
  6. stompClient.connect({}, function(frame) {
  7. setConnected(true);
  8. console.log('Connected: ' + frame);
  9. stompClient.subscribe('/personal', function(greeting){
  10. console.log(JSON.parse(greeting.body));
  11. });
  12. });
  13. stompClient.send(`/app/group/${groupName}/join`, {}, JSON.stringify({}));
  14. }
  15. function sendMessage() {
  16. const groupName = document.getElementById('groupInput').value;
  17. const messageContent = document.getElementById('messageInput').value;
  18. stompClient.send(`/app/group/${groupName}/send`, {}, JSON.stringify({ content: messageContent }));
  19. }
  20. </script>


FE视图

我的期望:
用户一:输入“组1”并加入
用户二:输入“组1”并加入
用户3:键入“group2”并加入
当用户1发送消息时,它应该只传递给用户1和2的WebSocket。
调试时,没有任何用户的websockets中的新消息或任何事件的日志。sendToGroup方法被触发,会话ID不为空
编辑:通过遵循这个Spring session + Spring web socket. Send message to specific client based on session id我已经更新了这样的代码发送消息,但仍然不工作

  1. SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor
  2. .create(SimpMessageType.MESSAGE);
  3. headerAccessor.setSessionId(session);
  4. headerAccessor.setLeaveMutable(true);
  5. simpMessagingTemplate.convertAndSendToUser(session,"/personal",message.getPayload(),headerAccessor.getMessageHeaders());


然而,通过此代码,消息在所有WebSocket示例中接收

  1. simpMessagingTemplate.convertAndSend("/personal",message.getPayload(),headerAccessor.getMessageHeaders());

6tr1vspr

6tr1vspr1#

看起来,当我们使用convertAndSendToUser()方法时,我们需要将/user添加到订阅路径中,在我的示例中
变化

  1. stompClient.subscribe('/personal', function(greeting){
  2. console.log(JSON.parse(greeting.body));
  3. });

字符串

  1. stompClient.subscribe('/user/personal', function(greeting){
  2. console.log(JSON.parse(greeting.body));
  3. });


但单靠这些并不能解决我的问题
所以有一个替代的方法来实现这一点,我测试和它的工作.
我们将不使用会话ID,而是使用要传递给convertAndSendToUser()的用户名
为了实现这一点,
首先创建一个HandShakeHandler

  1. public class CustomHandShakeHandler extends DefaultHandshakeHandler {
  2. @Override
  3. protected Principal determineUser(ServerHttpRequest request,
  4. WebSocketHandler wsHandler,
  5. Map<String, Object> attributes) {
  6. return new UserPrincipal(UUID.randomUUID().toString());
  7. }
  8. }


在配置中添加此内容

  1. @Override
  2. public void registerStompEndpoints(StompEndpointRegistry registry) {
  3. registry.addEndpoint("/ws-reg")
  4. .setHandshakeHandler(new CustomHandShakeHandler())
  5. .withSockJS();
  6. }


最后,我们需要做的就是使用主用户名而不是使用会话ID。
也不需要在convertAndSendToUser()方法中发送HTTP MessageHeaderAccessor数据。

展开查看全部
57hvy0tb

57hvy0tb2#

我也遇到了同样的问题,使用setAllowedOriginPatterns对我很有效。我已经修改了你的代码;试试这个,它应该可以工作。

  1. @Configuration
  2. @EnableWebSocketMessageBroker
  3. public class WebSockConfig implements WebSocketMessageBrokerConfigurer {
  4. @Override
  5. public void registerStompEndpoints(StompEndpointRegistry registry) {
  6. registry.addEndpoint("/wsreg").setAllowedOriginPatterns("*").withSockJS();
  7. }
  8. @Override
  9. public void configureMessageBroker(MessageBrokerRegistry config) {
  10. config.setApplicationDestinationPrefixes("/app");
  11. config.enableSimpleBroker("/all","/personal");
  12. }
  13. }

字符串

展开查看全部

相关问题