Spring搭建WebSocket接口提供给前端进行长连接

tech2023-08-30  87

在项目开发中,通常使用ajax或者axios进行短连接的后台接口请求,当前端想要数据时,进行主动请求。若前端需要即时的知晓后台数据变化情况时,用ajax进行定时刷新接口请求才能实现。但是也相应的会出现一些负面影响,比如后台接口调用频繁等。这个场景下就需要创建一个长连接来进行解决此问题,前端与后台进行连接后,不仅前端可以实时与后端进行通信,后端也可以主动将数据推送至前端,以下是实现逻辑,分为JAVA和JS两部分。

1.JAVA新建WebSocket类,并先实现基础触发器方法。

     a.加入注解@ServerEndpoin("/websocket") 申明当前websocket的请求地址

     b.编写webSocket必备的方法:

           @OnOpen-连接成功时,调用

@OnOpen public void onOpen(Session session) throws Exception { this.session = session; webSocketMap.put(session.getQueryString(), this); }

           @OnClose-连接关闭时调用

@OnClose public void onClose() throws Exception { //从map中删除 webSocketMap.remove(session.getQueryString()); }

           @OnMessage-客户端发消息来时调用

@OnMessage public void onMessage(String message, Session session) { try { WebSocket myWebSocket = (webSocketMap.get(session.getQueryString().replace("service", "client"))); if (myWebSocket != null) { myWebSocket.sendMessage(message); } System.out.println("接收消息" + message); sendMessageAll(message); } catch (IOException e) { e.printStackTrace(); } }

           @OnError-发生错误时调用

/** * 发生错误时调用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); }

   c.编写新增连接时的方法

          当产生新的连接时,首先获取当前连接的session并将当前连接已key&value的形式进行保存备用。

@OnOpen public void onOpen(Session session) throws Exception { this.session = session; webSocketMap.put(session.getQueryString(), this); }

注意:websocket连接必须将当前连接的标志位信息进行保存,否则后续服务端主动推送数据给前端时无法查找到前端。

完整WebSocket基础代码:

@ServerEndpoint(value = "/websocket") public class WebSocket { /** * 与某个客户端的连接会话,需要通过它来给客户端发送数据 **/ public Session session; /** * @Description: 保存session信息 * @Date 11:32 2019/6/14 * @return **/ public final static ConcurrentMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>(); /** * 连接建立成功调用的方法 * * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 * @throws Exception */ @OnOpen public void onOpen(Session session) throws Exception { this.session = session; webSocketMap.put(session.getQueryString(), this); } /** * 连接关闭调用的方法 * * @throws Exception */ @OnClose public void onClose() throws Exception { //从map中删除 webSocketMap.remove(session.getQueryString()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 * @param session 可选的参数 * @throws IOException */ @OnMessage public void onMessage(String message, Session session) { try { WebSocket myWebSocket = (webSocketMap.get(session.getQueryString().replace("service", "client"))); if (myWebSocket != null) { myWebSocket.sendMessage(message); } System.out.println("接收消息" + message); sendMessageAll(message); } catch (IOException e) { e.printStackTrace(); } } /** * 发生错误时调用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); } /** * 发送消息方法。 * * @param message * @throws IOException */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 群发消息方法。 * * @param message * @throws IOException */ public void sendMessageAll(String message) throws IOException { for (WebSocket myWebSocket : webSocketMap.values()) { myWebSocket.sendMessage(message); } } }

 

解析当前触发器需要发送给哪些前端客户端,根据前端创建webSocket时,query参数中携带的标识信息进行区分和解析。

后台主动发送数据给前端的代码:

public void sendMessage( Map<String, Object> map, Integer type) { try { for (WebSocket myWebSocket : WebSocket.webSocketMap.values()) { String[] userId = getUserIdByQuerId(myWebSocket.session.getQueryString()); if (userId != null && userId.length > 1) { //发送 if (type == 2 && userId[0].equals("Type")) { log.info("发送信息给前端!!!!!!!!!!id:" + myWebSocket.session.getQueryString()); myWebSocket.sendMessage("$" + JsonUtils.objectToJson(map)); } // } } } } catch (IOException e) { e.printStackTrace(); } }

 

前端js进行websocket连接操作:

a.创建websocket连接

_this.socketurl='ws://127.0.0.1:8089/DataBus/websocket?'; var randomNum = "Type_" + sessionStorage.getItem("userId") + "_" + ("000000" + Math.floor(Math.random() * 999999)).slice(-6); this.socket = new WebSocket(this.socketurl + randomNum); this.socket.onopen = function(event) { console.log("连接成功"); };

randomNum主要分为三部分:类型+用户id+随机数,用于后台进行获取当前连接信息。

b.获取后端返回的数据

this.socket.onmessage = function(event) { if (event.data.substr(0, 1) == "$") { let data = JSON.parse(event.data.slice(1)); //解析数据,并进行一些数据操作 });

c.监测当websocket关闭时,进行重连操作

this.socket.onclose = function(event) { console.log("关闭了,进行几分钟重连一次"); };

 

 

最新回复(0)