首先后端创建一个WebSocketConfig 配置类

@Configuration
public class WebSocketConfig {
    /**
     * 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

之后创建一个websoket 连接收发类

这里当前端访问/test/oneToMany/{userId} 建立连接,其中{userId} 为前端传过来当前用户的Id 值。

  1. 首先第一步、前端访问连接地址为ws://localhost:8080/test/oneToMany/123456
  2. 之后会进入onOpen 方法**(注意加@OnOpen注解**)连接建立成功调用的方法。获取到用户id 为123456,和生成连接会话Session 对象
  3. 将Session 根据id 放入clients中保存
  4. onMessage( 注意加@OnMessage)方法为服务器端收到客户端消息后回调方法;
  5. 当需要发送发送消息时可根据用户id 拿到对应的Session 对象调用session.getAsyncRemote().sendText(“你要发送的消息”);进行发送。
  6. 当用户关闭浏览器,或断开连接后。会回调onClose方法(注意加 @OnClose注解)将之前保存的Session会话对象移除。
/**
 *
 * 前后端交互的类实现消息的接收推送(自己发送给所有人(不包括自己))
 *
 * @ServerEndpoint(value = "/test/oneToMany") 前端 和后端交互,建立连接
 */
@Slf4j
@ServerEndpoint(value = "/test/oneToMany/{userId}")
@Component
public class OneToManyWebSocket {

    /** 记录当前在线连接数 */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /** 存放所有在线的客户端 key 为用户Id */
    private static Map<String, Session> clients = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") String userId) {
        if(clients.containsKey(userId)){
            clients.remove(userId);
            clients.put(userId, session);
        }else{
            onlineCount.incrementAndGet(); // 在线数加1
            clients.put(userId, session);
            sendMessage("你好啊客户端"+userId,session);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        for (String userId : clients.keySet()) {
            if(clients.get(userId).equals(session)){
                clients.remove(session);
                onlineCount.decrementAndGet(); // 在线数减1
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
        //this.sendMessage(message, session);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 群发消息
     *
     * @param message
     *            消息内容
     */
    public void sendMessage(String message, Session fromSession) {
        for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
            Session toSession = sessionEntry.getValue();
            // 排除掉自己
            //if (!fromSession.getId().equals(toSession.getId())) {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getAsyncRemote().sendText(message);
            //}
        }
    }

    /**
     * 群发消息
     *
     * @param message
     *            消息内容
     */
    public void sendMessage(String message, List<String> ids) {

        for (String id : ids) {
            Session session = clients.get(id);
            if(session!=null){
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                try {
                    session.getAsyncRemote().sendText(message);
                }catch (Exception e){
                    log.info("数据发送失败!疑似断开连接", session.getId(), message);
                    clients.remove(id);
                }
            }
        }
    }

    public Session getUserSession(String userId){
        return clients.get(userId);
    }
}

前端测试连接

	var websocket = null;
    //判断当前浏览器是否支持WebSocket, 主要此处要更换为自己的地址
    if ('WebSocket' in window) {
      var socketPath = layui.setter.socketPath; // ws://localhost:8080/test/oneToMany/
      var userId = $("#user").attr("value"); // 0
      websocket = new WebSocket(socketPath+userId); //ws://localhost:8080/test/oneToMany/0
      window.websocket = websocket;
    } else {
      layer.msg("抱歉!您的浏览器不支持websocket可能影响部分功能体验,请升级您的浏览器");
    }

    //连接发生错误的回调方法
    websocket.onerror = function() {
      layer.msg("error");
    };

    //连接成功建立的回调方法
    websocket.onopen = function(event) {
      //setMessageInnerHTML("open");
      send("你好啊服务器");
    }

    //接收到消息的回调方法
    websocket.onmessage = function(event) {
      layer.msg(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function() {
      layer.msg("close");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function() {
      websocket.close();
    }

    //关闭连接
    function closeWebSocket() {
      websocket.close();
    }

    //发送消息
    function send(message) {
     // var message = document.getElementById('text').value;
      websocket.send(message);
    }

完成测试

测试

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐