> 文章列表 > 浅测SpringBoot环境中使用WebSocket(多端实时通信)

浅测SpringBoot环境中使用WebSocket(多端实时通信)

浅测SpringBoot环境中使用WebSocket(多端实时通信)

目录

概述

测试:前端代码

后端代码(SpringBoot环境)

 1.创建处理器类(用于处理连接和消息

2.创建配置类(用于注册处理器类,开启WebSocket)

连接测试


概述

 这篇博客主要是记录测试使用WebSocket的过程。

需求说明:最近在做一个预约系统,有用户端和医生端,用户端展示着自己的预约信息和其他用户的预约信息,医生端展示着所有人的预约信息和操作按钮,医生端是可以进行预约的处理,例如"接诊","完成"和"错过时间"等处理操作,当医生进行这类操作以后,需要通知到所有用户端进行数据更新,以展示最新的预约状态。

总结:医生端操作,服务器广播消息给所有连接的用户端,用户端接收到消息进行数据的重新获取,进行数据实时更新。

需求分析:根据需求,我们只要做到医生端建立连接并向服务器发送指定内容,服务器接收到指定内容后,向所有已连接上的客户端发送更新指令(广播),客户端接收到后进行数据的重新获取展示,就能达到根据医生操作数据实时更新数据的效果。

实现

1.定时轮询:为了达到如上需求,我们可以进行定时轮询,也就是定时向服务器获取最新的数据,这是种简单的实现思路,但是耗性能并且实时更新的效率也不高。

2.WebSocket:使用WebSocket的话就好了许多,只需要用户端向服务器进行一次连接,那么就能进行多次通信,并且通信可以是双向的。如下使用此方式实现演示。

测试:前端代码

前端代码创建WebSocket对象,连接并发送消息。

简单测试界面:

 前端代码(原生JS实现)

<div id="container"><h2>WebSocketTest</h2><br>内容<input type="text" id="myInput"><br><br><button id="linkServer">连接并发送消息</button>
</div><script>// 获取输入框内容-发送的消息let myInput =  document.querySelector("#myInput")// 发送按钮,触发连接并发送消息。document.querySelector("#linkServer").onclick = function(){// 触发下方方法connect(myInput.value);}// 创建WebSocket对象并发送消息,接收消息。function connect(sendMsg){// 创建WebSocket对象// ws://localhost:8787/myWebSocket为后端开放的访问路径const socket = new WebSocket('ws://localhost:8787/myWebSocket');// 监听连接打开事件socket.onopen = function(event) {console.log('WebSocket连接已打开');// 发送消息socket.send(sendMsg);console.log("客户端发送的消息是:",sendMsg);};// 监听接收消息事件socket.onmessage = function(event) {console.log('接收到消息:', event.data);};// 监听连接关闭事件socket.onclose = function(event) {console.log('WebSocket连接已关闭');};// 监听连接错误事件socket.onerror = function(event) {console.error('WebSocket连接发生错误');};}
</script>

后端代码(SpringBoot环境)

导入依赖(pom.xml)

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.5</version>
</dependency>

 1.创建处理器类(用于处理连接和消息)

package com.mh.common;import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;import java.util.ArrayList;
import java.util.List;/*** Date:2023/4/20* author:zmh* description: WebSocket消息处理类**/@Component
public class MyWebSocketHandler implements WebSocketHandler {// 维护所有连接会话的列表private List<WebSocketSession> sessions = new ArrayList<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {// 将新连接的Session加入到集合中this.sessions.add(session);}@Overridepublic void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {// 获取前端传入的消息String payload = (String) message.getPayload();// 根据传入消息不同,响应不同消息if ("student".equals(payload)){session.sendMessage(new TextMessage("student,hi!"));} else if ("doctor".equals(payload)) {session.sendMessage(new TextMessage("doctor,hi!"));} else if ("maohe101".equals(payload)) {// 广播前将此临时通知连接删除,因为我们每次发送广播通知前端都会新创建一个连接。session.close();// 将消息广播到所有已连接的会话上for (WebSocketSession s : this.sessions) {s.sendMessage(new TextMessage("预约信息已变更,请重载数据!"));}}else {session.sendMessage(new TextMessage("你好!"));}}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {// 处理错误的连接,将连接删除this.sessions.remove(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {// 处理主动关闭的连接this.sessions.remove(session);}@Overridepublic boolean supportsPartialMessages() {// 关闭部分消息的处理,等待所有消息到达后在做处理return false;}
}

2.创建配置类(用于注册处理器类,开启WebSocket)

package com.mh.config;import com.mh.common.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/*** Date:2023/4/20* author:zmh* description: WebSocket配置类**/@Configuration 
@EnableWebSocket // 开启WebSocket
public class MyWebSocketConfig implements WebSocketConfigurer {// 注入自定义的处理器类@Autowiredprivate MyWebSocketHandler myWebSocketHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 注册自定义处理器类,指定访问入口,并指定所有源均可连接WebSocketregistry.addHandler(myWebSocketHandler,"/myWebSocket").setAllowedOrigins("*");}
}

连接测试

 根据后端代码,当服务器接收到前端发送的消息:"maohe101"之后,就会广播指定消息:”预约信息已变更,请重载数据!“,那么客户端接收到此广播的消息,就进行数据的重新拉取,实现数据的实时更新。这也就解决了我们的需求,当医生端操作后,就向服务器发送"maohe101"那么就能实现通知所有客户端更新数据的需求了。

模拟客户端连接

模拟医生端连接

医生端发送更新指令(触发广播消息)

----------------

===> 至此,测试完毕。<===