一、搭建一个简单的springBoot项目,导入以下jar包

 <dependency>
         <groupId>javax</groupId>
         <artifactId>javaee-api</artifactId>
         <version>7.0</version>
         <scope>provided</scope>
 </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

二,编写WebSocket服务

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket支持
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/notice/{userId}")
@Component
@Slf4j
public class NoticeWebsocket {

  //记录连接的客户端
  public static Map<String, Session> clients = new ConcurrentHashMap<>();

  /**
   * userId关联sid(解决同一用户id,在多个web端连接的问题)
   */
  public static Map<String, Set<String>> conns = new ConcurrentHashMap<>();

  private String sid = null;

  private String userId;


  @OnOpen
  public void onOpen(Session session, @PathParam("userId") String userId) {
    String tempSid = session.getId();
    this.sid = tempSid;
    this.userId = userId;
    clients.put(tempSid, session);

    Set<String> clientSet = conns.get(userId);
    if (clientSet==null){
      clientSet = new HashSet<>();
      conns.put(userId,clientSet);
    }
    clientSet.add(tempSid);
    log.error("DeviceWebsocket---onOpen===>id:{}--{}--连接数:{}--在线数:{}--当前设备连接数:{}", userId, tempSid, clients.size(), conns.size(), conns.get(userId).size());
  }

  @OnClose
  public void onClose(Session session, @PathParam("userId") String userId) {
    String tempSid = session.getId();
    //log.info(this.sid + "连接断开!");
    closeSession(tempSid, userId);
  }

  public void closeSession(String sid, String userId){
    Session s  = clients.remove(sid);
    if (s!=null){
      try {
        s.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    Set<String> clientSet = conns.get(userId);
    if (clientSet!=null){
      clientSet.remove(sid);
    }
    int currentConnectCount = clientSet.size();
    if(clientSet!=null && clientSet.size()==0){
      conns.remove(userId);
      currentConnectCount = 0;
    }
    log.error("DeviceWebsocket---onClose===>id:--{}--{}--连接数:{}--在线数:{}--当前设备连接数:{}", userId, sid, clients.size(), conns.size(), currentConnectCount);
    //log.error("在线人数===="+clients.size());
  }

  public static void sendMessage(String noticeType){
    NoticeWebsocketResp noticeWebsocketResp = new NoticeWebsocketResp();
    noticeWebsocketResp.setNoticeType(noticeType);
    sendMessage(noticeWebsocketResp);
  }


  /**
   * 发送给所有用户
   * @param noticeWebsocketResp
   */
  public static void sendMessage(NoticeWebsocketResp noticeWebsocketResp){
    String message = JSONObject.toJSONString(noticeWebsocketResp);
    for (Session session1 : NoticeWebsocket.clients.values()) {
      try {
        session1.getBasicRemote().sendText(message);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * 根据用户id发送给某一个用户
   * **/
  public static void sendMessageByUserId(String userId, NoticeWebsocketResp noticeWebsocketResp) {
    if (!StringUtils.isEmpty(userId)) {
      String message = JSONObject.toJSONString(noticeWebsocketResp);
      Set<String> clientSet = conns.get(userId);
      if (clientSet != null) {
        Iterator<String> iterator = clientSet.iterator();
        while (iterator.hasNext()) {
          String sid = iterator.next();
          Session session = clients.get(sid);
          if (session != null) {
            try {
              session.getBasicRemote().sendText(message);
            } catch (IOException e) {
              e.printStackTrace();
            }
          }else {
            iterator.remove();;
          }
        }
      }
    }
  }

  @OnError
  public void onError(Throwable error) {
    error.printStackTrace();
  }

}

三、构建一个返回对象

@Data
@ApiModel("ws通知返回对象")
public class NoticeWebsocketResp<T> {

    @ApiModelProperty(value = "通知类型")
    private String noticeType;

    @ApiModelProperty(value = "通知内容")
    private T noticeInfo;

}

四、测试结果(这里我用的是在线的webSocket工具:在线websocket测试-在线工具-postjson)

NoticeWebsocket---onOpen===>id:666666--CXD6bnRwNCxDi-AD-UjwIRpXNIVupeV2KYTCrf8f--连接数:1--在线数:1--当前设备连接数:1
NoticeWebsocket---onOpen===>id:666666--WG4tDa22d50iCChcMb5XQ0yeuob7h6KyoywJs_5h--连接数:2--在线数:1--当前设备连接数:2
NoticeWebsocket---onOpen===>id:666666--109ZAVijoO0_eslj6V0LdzaROGRUPaoG7ctT6UsA--连接数:3--在线数:1--当前设备连接数:3
NoticeWebsocket---onOpen===>id:777777--p2TgD2r9u4IQj7gOXbH9yBvlSyNJ4hYszE3QGr6S--连接数:4--在线数:2--当前设备连接数:1
NoticeWebsocket---onClose===>id:--666666--WG4tDa22d50iCChcMb5XQ0yeuob7h6KyoywJs_5h--连接数:3--在线数:2--当前设备连接数:2

Logo

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

更多推荐