您现在的位置是:首页 >技术杂谈 >浅测SpringBoot环境中使用WebSocket(多端实时通信)网站首页技术杂谈
浅测SpringBoot环境中使用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<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 将新连接的Session加入到集合中
this.sessions.add(session);
}
@Override
public 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("你好!"));
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// 处理错误的连接,将连接删除
this.sessions.remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
// 处理主动关闭的连接
this.sessions.remove(session);
}
@Override
public 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 {
// 注入自定义的处理器类
@Autowired
private MyWebSocketHandler myWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册自定义处理器类,指定访问入口,并指定所有源均可连接WebSocket
registry.addHandler(myWebSocketHandler,"/myWebSocket").setAllowedOrigins("*");
}
}
连接测试
根据后端代码,当服务器接收到前端发送的消息:"maohe101"之后,就会广播指定消息:”预约信息已变更,请重载数据!“,那么客户端接收到此广播的消息,就进行数据的重新拉取,实现数据的实时更新。这也就解决了我们的需求,当医生端操作后,就向服务器发送"maohe101"那么就能实现通知所有客户端更新数据的需求了。
模拟客户端连接
模拟医生端连接
医生端发送更新指令(触发广播消息)
----------------
===> 至此,测试完毕。<===