【问题标题】:Websocket keep track of connections in SpringWebsocket 跟踪 Spring 中的连接
【发布时间】:2025-12-26 00:05:06
【问题描述】:

今天我搜索了几个小时来寻找有关如何在 Spring 中跟踪 websocket 连接的实现或教程。

我已经完成了关于 websockets 和 STOMP 的(非常好的)Spring 教程。 链接here

那么我的设置是什么,我有一个带有 Spring 后端的 Ionic Hybrid 应用程序,我想在后端出现新的通知事件时向客户端发送通知。所有这些代码都已经实现并且连接正常,但是现在无法指定通知需要去哪里。

没有关于这个问题的教程或解释遵循 Spring 教程中的结构(至少经过 5 个小时的研究之后没有),我对网络上关于 websockets 和安全性的所有信息有点不知所措。 (我学习 websockets 才 2 天)

因此,对于我之前和之后的所有内容,我认为按照 Spring 教程所教的结构获得一个紧凑且轻量级的答案可能非常有用。

我在 * 上发现了 this unanswered question 与我遇到的相同问题,所以我相信这些问题会证明它是值得的。

TL;DR

如何在后端实现一个列表来跟踪基于Spring WebSocket Tutorial的连接?

建立连接后如何将数据从客户端发送到后端? (例如用户 ID 或令牌)

【问题讨论】:

  • 你真的花时间阅读Reference Guide吗?
  • 我做到了,正如我所说的那样,这一切都令人难以抗拒,因此我认为一个简单而通用的答案对于像我这样的新学习者来说可能非常有用。

标签: java spring stomp spring-websocket sockjs


【解决方案1】:

所以我自己想通了。

我的通知有一个收件人 ID(需要发送通知的用户 ID)

所以我要发送到 '/ws-user/'+id+'/greetings',其中 id 是登录的用户。

在客户端这很容易实现。

 var stompClient = null;

  // init
  function init() {
          /**
           * Note that you need to specify your ip somewhere globally
           **/
      var socket = new SockJS('http://127.0.0.1:9080/ws-notification');
      stompClient = Stomp.over(socket);
      stompClient.connect({}, function(frame) {
          console.log('Connected: ' + frame);
          /**
           * This is where I get the id of the logged in user
           **/
          barService.currentBarAccountStore.getValue().then(function (barAccount) {
              subscribeWithId(stompClient,barAccount.user.id);
          });
      });
  }

          /**
           * subscribe at the url with the userid
           **/
  function subscribeWithId(stompClient,id){
      stompClient.subscribe('/ws-user/'+id+'/greetings', function(){
          showNotify();
      });
  }
          /**
           * Broadcast over the rootscope to update the angular view 
           **/
  function showNotify(){
      $rootScope.$broadcast('new-notification');
  }

  function disconnect() {
      if (stompClient != null) {
          stompClient.disconnect();
      }
      // setConnected(false);
      console.log("Disconnected");
  }

接下来我们在 WebSocketConfig.java 类的 MessageBrokerRegistry 中添加“setUserDestinationPrefix”:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    private final static String userDestinationPrefix = "/ws-user/";

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config){
        config.enableSimpleBroker("/ws-topic","/ws-user");
        config.setApplicationDestinationPrefixes("/ws-app");
        config.setUserDestinationPrefix(userDestinationPrefix);
    }

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

请注意,我正在使用内部 RestTemplate 调用来访问我的控制器方法,该方法会向订阅的客户端发送通知。这是由事件消费者类完成的(要求查看代码,它只是触发控制器功能,可以不同的方式完成)

@RequestMapping(value = "/test-notification", method = RequestMethod.POST)
public void testNotification(@RequestBody String recipientId) throws InterruptedException {
    this.template.convertAndSendToUser(recipientId,"/greetings", new Notify("ALERT: There is a new notification for you!"));
}

如果您发现任何问题和/或安全问题,请查看我的代码并警告我。

【讨论】:

  • 你能分享代码吗?你怎么知道使用哪个套接字向客户端发送消息?
  • @Sytham 你能分享一下代码吗?我一直在向客户端发送消息。谢谢。
【解决方案2】:

对于 websocket 中基于用户的交付,您可以使用具有 spring 安全性的 Principle 对象。这是一个很好的实现示例:

https://github.com/rstoyanchev/spring-websocket-portfolio

Spring security 将检查 SAME ORIGIN 并且您可以从您的客户端发送指定 used-id 的 stomp 标头。

希望这对你有帮助。

【讨论】:

    【解决方案3】:

    看看这个答案:How to get all active sessions in Spring 5 WebSocket API?

    您可以使用 Spring 的 SimpUserRegistry API 检索连接的用户。

    【讨论】: