企业网站上海熙,百度登录入口官网,站长统计网站统计,简历wordpress文章目录 前言相关技术简介什么是WebSocketWebSocket的原理WebSocket与HTTP协议的关系WebSocket优点WebSocket应用场景 实现方式1. 添加maven依赖2. 添加WebSocket配置类#xff0c;定义ServerEndpointExporter Bean3. 定义WebSocket Endpoint4. 前端创建WebSocket对象 总结 前… 文章目录 前言相关技术简介什么是WebSocketWebSocket的原理WebSocket与HTTP协议的关系WebSocket优点WebSocket应用场景 实现方式1. 添加maven依赖2. 添加WebSocket配置类定义ServerEndpointExporter Bean3. 定义WebSocket Endpoint4. 前端创建WebSocket对象 总结 前言
近日心血来潮想做一个开源项目目标是做一款可以适配多端、功能完备的模板工程包含后台管理系统和前台系统开发者基于此项目进行裁剪和扩展来完成自己的功能开发。 本项目为前后端分离开发后端基于Java21和SpringBoot3开发前端提供了vue、angular、react、uniapp、微信小程序等多种脚手架工程。 本文主要介绍项目中如何集成WebSocket实现服务器端与客户端的双向通信。
相关技术简介
什么是WebSocket
WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。 http是一种无状态无连接单向的应用层协议它采用了请求/响应模型通信请求只能由客户端发起服务端对请求做出应答处理。这样的弊端显然是很大的只要服务端状态连续变化客户端就必须实时响应都是通过javascript与ajax进行轮询这样显然是非常麻烦的同时轮询的效率低非常的浪费资源(http一直打开一直重复的连接)。 于是就有了WebSocket它是一种全面双工通讯的网络技术任意一方都可以建立连接将数据推向另一方WebSocket只需要建立一次连接就可以一直保持。
WebSocket的原理
WebSocket约定了一个通信的规范通过一个握手的机制客户端和服务器之间能建立一个类似tcp的连接从而方便它们之间的通信在WebSocket出现之前web交互一般是基于http协议的短连接或者长连接WebSocket是一种全新的协议不属于http无状态协议协议名为ws
WebSocket与HTTP协议的关系 WebSocket优点
减少请求费时费资源是真正的全双工方式建立连接后服务器与客户端时完全对等的可以相互请求减少了不必要的网络请求时间损耗和网络流量更持久WebSocket协议通过第一个request建立TCP连接后只要不主动关闭就能一直保持连接状态交换数据服务端可以主动向客户端发送消息
WebSocket应用场景
社交聊天、弹幕、多玩家游戏、协同编辑、股票基金实时报价、体育实况更新、视频会议/聊天、基于位置的应用、在线教育、智能家居等需要高实时的场景都可以使用WebSocket技术实现。
实现方式
本项目后端基于Java 21和SpringBoot3开发前端基于Vue3实现。
1. 添加maven依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactIdversion3.2.0/version
/dependency2. 添加WebSocket配置类定义ServerEndpointExporter Bean
Configuration
EnableWebSocket
public class WebSocketConfig {/*** 注入ServerEndpointExporter* 这个bean会自动注册使用了ServerEndpoint注解声明的WebSocket Endpoint*/Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
3. 定义WebSocket Endpoint
/*** 消息提醒计数WebSocket*/
ServerEndpoint(/ws/test/{userId})
Component
Slf4j
public class TestWebSocketServer {/*** 与某个客户端的连接会话需要通过它来给客户端发送数据*/private Session session;/*** 用户ID*/private Long userId;/*** concurrent包的线程安全Set用来存放每个客户端对应的MyWebSocket对象。* 虽然Component默认是单例模式的但springboot还是会为每个websocket连接初始化一个bean所以可以用一个静态set保存起来。*/private static final CopyOnWriteArraySetMessageCountWebSocketServer webSockets new CopyOnWriteArraySet();/*** 用来存在线连接用户信息*/private static final ConcurrentHashMapLong, Session sessionPool new ConcurrentHashMap();/*** 链接成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(value userId) Long userId) {this.session session;this.userId userId;webSockets.add(this);sessionPool.put(userId, session);log.info(建立与UserID{}的消息提醒计数连接, userId);}/*** 链接关闭调用的方法*/OnClosepublic void onClose() {webSockets.remove(this);sessionPool.remove(this.userId);log.info(关闭与UserID{}的消息提醒计数连接, userId);}/*** 收到客户端消息后调用的方法*/OnMessagepublic void onMessage(String message) {log.info(接收到UserID{}的消息{}, userId, message);}/*** 发送错误时的处理*/OnErrorpublic void onError(Session session, Throwable error) {log.error(发送到UserID{}的消息传输失败, userId, error);}/*** 广播消息** param message*/public void sendAllMessage(String message) {for (MessageCountWebSocketServer socketServer : webSockets) {if (socketServer.session.isOpen()) {socketServer.session.getAsyncRemote().sendText(message);}}}/*** 单人单播消息** param userId* param message*/public void sendOneMessage(Long userId, String message) {Session session sessionPool.get(userId);if (session ! null session.isOpen()) {session.getAsyncRemote().sendText(message);}}/*** 多人单播消息** param userIds* param message*/public void sendMoreMessage(Long[] userIds, String message) {for (Long userId : userIds) {Session session sessionPool.get(userId);if (session ! null session.isOpen()) {session.getAsyncRemote().sendText(message);}}}
}
4. 前端创建WebSocket对象
以下代码基于Vue3的组合式API编写。
script setupimport { onMounted, onBeforeMount } from vue;/*** type {WebSocket}*/let websocket null;onMounted(async () {initTestWebSocket();});onBeforeMount(async(){websocket websocket.close();});const initTestWebSocket async () {const userId 当前用户ID;console.log(尝试建立websockect连接);websocket new WebSocket(/ws/test/${userId});websocket.onopen function (event) {console.log(建立连接);}websocket.onclose function (event) {console.log(连接关闭)//尝试重连websocketreconnectMessageWebSocket();}//建立通信后监听到后端的数据传递websocket.onmessage function (event) {// 打印后端传来的数据console.log(event.data);// 调用WebSocket对象的send方法可向后端发送数据// websocket.send(test data);}websocket.onerror function () {console.log(数据发送失败);}// 窗口关闭前关闭WebSocket连接window.onbeforeunload function () {websocket.close();}};// 重连const reconnectMessageWebSocket () {console.log(正在重连);// 进行重连setTimeout(() {initTestWebSocket();}, 1000);}
/script总结
本文介绍了WebSocket的相关概念以及如何基于Java21、SpringBoot3和Vue3使用WebSocket在使用过程中也遇到了一些问题。 执行mvn package或mvn test命令时报错 请参阅 Java21 SpringBoot3使用spring-websocket时执行mvn package报错。 如果后端使用Spring Security、Shiro或Sa-Token等技术需要考虑使用ServerEndpoint注解所配置url的权限控制问题。
我也会及时的更新后续实践中所遇到的问题希望与诸位看官一起进步。 如有错误还望批评指正。