New file |
| | |
| | | package com.dy.pipIrrRemote.largeScreen; |
| | | |
| | | import com.dy.common.aop.SsoCheck; |
| | | import com.dy.common.aop.SsoVo; |
| | | import com.dy.common.springUtil.SpringContextUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Scope; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import jakarta.websocket.*; |
| | | import jakarta.websocket.server.PathParam; |
| | | import jakarta.websocket.server.ServerEndpoint; |
| | | import java.io.IOException; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/2/10 15:25 |
| | | * @Description 客户端(浏览器)每建立一个websocket连接,服务端就会创建一个WebSocketServer实例 |
| | | * 应用前提是存在一个Config类,如本模块的WebSocketConfig,这时@ServerEndpoint受SpringBoot容器 |
| | | * 管理了(在嵌入式web Servlet环境中) |
| | | */ |
| | | @Slf4j |
| | | @ServerEndpoint("/websocket/ls/{token}") |
| | | @Component |
| | | @Scope("prototype") // 非单例,每次请求都会创建新的实例 |
| | | public class WebSocketServer { |
| | | |
| | | // 静态变量,记录当前在线连接数 |
| | | private static int onlineCount = 0; |
| | | |
| | | // 存放每个客户端对应的WebSocketServer对象 |
| | | private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>(); |
| | | |
| | | // 客户端连接会话,通过它给客户端发送数据 |
| | | private Session session; |
| | | |
| | | private String orgTag; |
| | | |
| | | // 客户端上线时刻 |
| | | //private String onLineDt ; |
| | | // 客户端 |
| | | private String token = ""; |
| | | |
| | | @Autowired |
| | | private SsoCheck ssoCheck ; |
| | | |
| | | /** |
| | | * 连接建立成功调用的方法 |
| | | * @param session websocket会话对象 |
| | | * @param token 客户端id |
| | | */ |
| | | @OnOpen |
| | | public void onOpen(Session session, @PathParam("token") String token) { |
| | | if(this.token == null || this.token.length() == 0){ |
| | | this.session = session; |
| | | //this.onLineDt = DateTime.yyyy_MM_dd_HH_mm_ss() ; |
| | | this.token = token; |
| | | this.sendMessage(WebSocketHeartBeat.getHeartBeatMessage()); |
| | | |
| | | if (webSocketMap.containsKey(token)) { |
| | | webSocketMap.remove(token); |
| | | webSocketMap.put(token, this); |
| | | } else { |
| | | webSocketMap.put(token, this); |
| | | WebSocketServer.addOnlineCount(); |
| | | } |
| | | if(this.ssoCheck == null){ |
| | | //2025-07-22 不知为什么,this.ssoCheck会为null |
| | | this.ssoCheck = SpringContextUtil.getBean(SsoCheck.class); |
| | | } |
| | | Object rObj = this.ssoCheck.check(token); |
| | | if(rObj != null) { |
| | | if (rObj instanceof SsoVo ssoVo) { |
| | | this.orgTag = ssoVo.dataSourceName ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 连接关闭调用的方法 |
| | | */ |
| | | @OnClose |
| | | public void onClose() { |
| | | if (webSocketMap.containsKey(token)) { |
| | | webSocketMap.remove(token); |
| | | //从set中删除 |
| | | WebSocketServer.subOnlineCount(); |
| | | } |
| | | log.info("客户端:" + token + ",关闭了websocket"); |
| | | } |
| | | |
| | | /** |
| | | * 收到客户端消息后调用的方法 |
| | | * @param message 客户端发送过来的消息 |
| | | * @param session |
| | | */ |
| | | @OnMessage |
| | | public void onMessage(String message, Session session) { |
| | | log.info("客户端:" + token + ",websocket报文:" + message); |
| | | } |
| | | |
| | | /** |
| | | * 会话异常 |
| | | * @param session |
| | | * @param error |
| | | */ |
| | | @OnError |
| | | public void onError(Session session, Throwable error) { |
| | | log.error("客户端:" + this.token + ",websocket会话异常,原因:" + error.getMessage()); |
| | | } |
| | | |
| | | /** |
| | | * 服务器主动推送消息 |
| | | */ |
| | | public void sendMessage(String message) { |
| | | try{ |
| | | this.session.getBasicRemote().sendText(message); |
| | | }catch (Exception e){ |
| | | log.error("客户端:" + token + ",websocket网络发送数据异常", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 服务器主动群推送消息 |
| | | */ |
| | | public static void sendMessage2AllClient(String orgTag, String message) throws IOException { |
| | | ConcurrentHashMap.KeySetView<String, WebSocketServer> tokens = webSocketMap.keySet(); |
| | | for (String token : tokens) { |
| | | WebSocketServer webSocketServer = webSocketMap.get(token); |
| | | if(orgTag == null){ |
| | | webSocketServer.sendMessage(message); |
| | | }else{ |
| | | if(webSocketServer.orgTag != null && webSocketServer.orgTag.equals(orgTag)){ |
| | | webSocketServer.sendMessage(message); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 服务器指定客户端推送消息 |
| | | */ |
| | | public static void sendMessage2OneClient(String message, String token) throws IOException { |
| | | if (message != null && message.length() != 0 && webSocketMap.containsKey(token)) { |
| | | webSocketMap.get(token).sendMessage(message); |
| | | } else { |
| | | log.error("客户端" + token + ",不在线!"); |
| | | } |
| | | } |
| | | |
| | | public static synchronized int getOnlineCount() { |
| | | return onlineCount; |
| | | } |
| | | |
| | | public static synchronized void addOnlineCount() { |
| | | WebSocketServer.onlineCount++; |
| | | } |
| | | |
| | | public static synchronized void subOnlineCount() { |
| | | WebSocketServer.onlineCount--; |
| | | } |
| | | } |