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

ghg1uchk  于 4个月前  发布在  Spring
关注(0)|答案(2)|浏览(74)

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

@Configuration
@EnableWebSocketMessageBroker
public class WebSockConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws-reg").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/all","/personal");
    }
}

字符串
控制器

@Controller
    public class HomeController {
        @Autowired
        private SimpMessagingTemplate simpMessagingTemplate;

        private final Map<String, List<String>> groupSessions = new HashMap<>();

        @MessageMapping("/group/{groupName}/join")
        public void joinGroup(@DestinationVariable String groupName, SimpMessageHeaderAccessor headerAccessor) {
            groupSessions.computeIfAbsent(groupName, k -> new ArrayList<>()).add(headerAccessor.getSessionId());

        }
        @MessageMapping("/group/{groupName}/send")
        public void sendToGroup(@DestinationVariable String groupName, Message<String> message) throws IOException {
            for ( String  session : groupSessions.get(groupName)){
                simpMessagingTemplate.convertAndSendToUser(session,"/personal",message.getPayload());
            }
        }
    }


HTML中的JavaScript

<script>
        const socket = new SockJS('http://localhost:8080/ws-reg');

        const stompClient = Stomp.over(socket);

        function joinGroup() {
            const groupName = document.getElementById('groupInput').value;

            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/personal', function(greeting){
                    console.log(JSON.parse(greeting.body));
                });
            });

            stompClient.send(`/app/group/${groupName}/join`, {}, JSON.stringify({}));
        }

        function sendMessage() {
            const groupName = document.getElementById('groupInput').value;
            const messageContent = document.getElementById('messageInput').value;
            stompClient.send(`/app/group/${groupName}/send`, {}, JSON.stringify({ content: messageContent }));
        }
 </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我已经更新了这样的代码发送消息,但仍然不工作

SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor
                    .create(SimpMessageType.MESSAGE);
            headerAccessor.setSessionId(session);
            headerAccessor.setLeaveMutable(true);

simpMessagingTemplate.convertAndSendToUser(session,"/personal",message.getPayload(),headerAccessor.getMessageHeaders());


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

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

6tr1vspr

6tr1vspr1#

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

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

字符串

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


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

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


在配置中添加此内容

@Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws-reg")
                .setHandshakeHandler(new CustomHandShakeHandler())
                .withSockJS();
    }


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

57hvy0tb

57hvy0tb2#

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

@Configuration
@EnableWebSocketMessageBroker
public class WebSockConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
       registry.addEndpoint("/wsreg").setAllowedOriginPatterns("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/all","/personal");
    }
}

字符串

相关问题