WebSocket的基本使用方法
一. 与HTTP对比
WebSocket 是一种在单个 TCP 连接上实现全双工(双向)通信的网络协议,它解决了传统 HTTP 协议 “请求 - 响应” 模式的局限性,让客户端(如浏览器)和服务器能建立持久连接,实现实时数据交互。
HTTP是短链接且单向通信,只有客户端主动发请求,服务器才能被动响应,无法主动向客户端推数据。WebSocket是长连接且支持双向通信
WebSocket通过一次HTTP握手建立持久TCP连接,之后客户端与服务器可基于该连接全双工、实时双向收发数据,无需反复建立连接。
二. WebSocket的关键特性
- 全双工通信:客户端和服务器可同时发送数据,无需等待对方响应。
- 持久连接:连接建立后长期保持,除非主动断开(如客户端关闭页面、服务器重启)。
- 跨域支持:WebSocket 本身支持跨域(类似 CORS),可通过
Origin
请求头和服务器配置控制跨域权限。 - 支持二进制数据:不仅能传文本(如 JSON),还能直接传二进制数据(如图片、音频、视频流),比 HTTP 传输二进制更高效。
- 自动重连(需手动实现):原生 WebSocket 不支持自动重连,实际项目中需通过代码逻辑实现(如监听
onclose
事件,延迟后重新发起连接)。
三. WebSocket 的典型应用场景
只要涉及 “实时数据交互” 的场景,WebSocket 都是优选方案:
- 即时通讯:在线聊天(如微信网页版、企业 IM)、客服对话。
- 实时通知:订单状态更新(如 “订单已发货”)、消息推送(如点赞提醒)。
- 实时数据展示:股票 / 数字货币行情、体育赛事比分、监控系统数据(如服务器 CPU 使用率)。
- 协同工具:多人在线文档编辑(如腾讯文档)、白板协作。
- 流媒体:低延迟的音视频通话(如 WebRTC 基于 WebSocket 做信令交互)、直播弹幕。
四. 实现步骤
1.前端(浏览器原生API)
浏览器内置WebSocket对象,可直接发送连接和处理数据。
这里以一个简单实现为例
<!DOCTYPE HTML>
<html>
<head><meta charset="UTF-8"><title>WebSocket Demo</title>
</head>
<body><input id="text" type="text" /><button onclick="send()">发送消息</button><button onclick="closeWebSocket()">关闭连接</button><div id="message"></div>
</body>
<script type="text/javascript">var websocket = null;var clientId = Math.random().toString(36).substr(2);//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);}else{alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(){setMessageInnerHTML("连接成功");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("close");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();}
</script>
</html>
2. 后端
2.1 导入WebSocket的maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.2 导入WebSocket服务端组件WebSocketServer,用于和客户端通信
/*** WebSocket服务*/
@Component // 交给 Spring 管理
@ServerEndpoint("/ws/{sid}")
//声明这是一个 WebSocket 服务端,路径为 /websocket/{sid}(支持路径参数)
public class WebSocketServer {//存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法* @param sid*/@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}/*** 群发* @param message*/public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}
WebSocketServer的代码格式基本就是这样,可以根据需要自行修改。
2.3 导入配置类WebSocketConfiguration,注册WebSocket的服务端组件
/*** WebSocket配置类,用于注册WebSocket的Bean*/
@Configuration
public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
前端和后端建立 WebSocket 连接的过程可分为 “握手” 和 “连接维持” 两步:
- 握手阶段:前端通过
new WebSocket('ws://服务器地址')
发起 HTTP 升级请求,携带Upgrade: websocket
等头信息;后端验证后返回101 Switching Protocols
响应,完成协议切换。 - 连接维持:握手成功后,TCP 连接保持持久状态,双方通过 WebSocket 帧格式直接双向收发数据,直到某一方主动关闭连接。
核心流程:前端发 HTTP 请求(带升级标识)→ 2. 后端验证并返回 101 响应 → 3. 协议切换为 WebSocket → 4. 基于持久 TCP 连接双向通信。
2.4 导入定时任务类WebSocketTask,定时向客户端推送数据
这相当于一个案例,如何使用WebSocketServer。
@Component
public class WebSocketTask {@Autowiredprivate WebSocketServer webSocketServer;/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}
}
当我们想向前端页面推送消息时WebSocketTask的方法sendMessageToClient,如果要传递一个对象,注意将其转换成json格式,例如:
Map map = new HashMap();map.put("type", 2);//1表示来单提醒 2表示客户催单map.put("orderId", id);map.put("content", "订单号:" + orders.getNumber());String json = JSON.toJSONString(map);// 通过WebSocket向客户端浏览器推送消息webSocketServer.sendToAllClient(json);