WebSocket 是一种在单个 TCP 连接上提供全双工通信的协议,其核心优势是服务器可主动向客户端推送数据,无需客户端频繁轮询,非常适合需要实时性、低延迟的场景。
一、 是什么
以下是其典型应用场景:
1. 即时通讯类
- 在线聊天:如网页版微信、企业内部 IM 系统,支持一对一、群聊实时消息推送。
- 客服系统:用户与在线客服的实时对话,消息秒级送达。
- 社交通知:新消息提醒、点赞 / 评论通知、好友上线提醒等。
2. 实时数据监控与展示
- 系统监控:服务器 CPU / 内存使用率、网络流量等指标的实时可视化(如监控大屏)。
- 物联网(IoT):设备传感器数据(温度、湿度、设备状态)实时上报与展示。
- 金融数据:股票 / 加密货币价格、汇率的实时波动更新。
3. 协作与互动场景
- 多人协作工具:在线文档(如腾讯文档)、表格的实时编辑同步,多用户操作即时反馈。
- 在线白板:远程会议中多人实时绘图、标注的同步展示。
- 实时投票 / 问卷:投票结果实时统计并更新显示。
4. 游戏场景
- 实时 multiplayer 游戏:如网页版棋牌游戏、休闲竞技游戏,玩家操作(移动、攻击)实时同步给其他玩家。
- 游戏状态同步:游戏房间人数变化、匹配状态、排行榜实时更新。
5. 实时推送服务
- 订单状态更新:电商平台订单支付、发货、配送状态的即时推送。
- 物流跟踪:快递位置实时更新,用户无需刷新页面即可看到最新进度。
- 新闻 / 资讯推送:突发新闻、个性化内容的实时推送(如体育赛事比分更新)。
6. 实时音视频相关
- 视频弹幕:直播平台的实时弹幕交互,观众发送的弹幕即时显示。
- 连麦互动:在线直播中主播与观众连麦时的信令交互(如请求连麦、挂断通知)。
二、怎么做
1. 导入关键 POM 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
2. 启动类添加注解 @EnableWebSocket
3. 添加扫描注解bean ServerEndpointExporter
@Bean
public ServerEndpointExporter serverEndpointExporter() {
// 扫描注解
ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter();
// 也可自定义 serverEndpointExporter.setAnnotatedEndpointClasses(WebSocketEndpoint.class);
return serverEndpointExporter;
}
4. 后端 注解方式 实现类 (监听 ws)
package com.bu.ws;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author haizhuangbu
* @date 12 8月 2025 15:00
* @mark WebScoketEndpoint
*/
@ServerEndpoint("/ws")
@Controller
public class WebSocketEndpoint {
private static final Set<WebSocketEndpoint> endpoints = new CopyOnWriteArraySet<>();
private static final Map<String, Session> sessions = new HashMap<>();
public WebSocketEndpoint() {
endpoints.add(this);
}
@OnOpen
public void onOpen(Session session) {
System.out.println("New connection opened: " + session.getId());
sessions.put(session.getId(), session);
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Received message from " + session.getId() + ": " + message);
for (WebSocketEndpoint endpoint : endpoints) {
try {
endpoint.sendMessage(session.getId(), message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@OnClose
public void onClose(Session session) {
System.out.println("Connection closed: " + session.getId());
endpoints.remove(this);
sessions.remove(session.getId());
}
@OnError
public void onError(Session session, Throwable throwable) {
System.out.println("Error in connection: " + session.getId());
throwable.printStackTrace();
endpoints.remove(this);
sessions.remove(session.getId());
}
public void sendMessage(String sessionId, String message) throws IOException {
Session session = sessions.get(sessionId);
if (session != null) {
session.getBasicRemote().sendText(message);
}
}
}
5. 前端 建立连接 ws (Vue)
initWebsocket() {
let wsUrl = 'ws://localhost:8990/ws'
this.webSocket = new WebSocket(wsUrl);
this.webSocket.onopen = this.ws_open;
this.webSocket.onerror = this.ws_error;
this.webSocket.onmessage = this.ws_message;
this.webSocket.onclose = this.ws_close;
},
ws_open() {
console.log('连接成功')
},
ws_error(e) {
console.log('连接失败')
},
ws_message(e) {
console.log('接收数据', e)
this.$message.info(e.data)
},
ws_close() {
console.log('关闭连接')
},
send_message() {
console.log('发送数据')
this.webSocket.send("我是发送数据");
}
6. 后端建立ws连接(客户端Client)
package com.bu.ws;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
/**
* @author haizhuangbu
* @date 13 8月 2025 09:10
* @mark WebSocketClient 客户端连接
*/
@Component
public class WebSocketClient {
public void connect() {
StandardWebSocketClient standardWebSocketClient = new StandardWebSocketClient();
// URI uri = UriComponentsBuilder.fromHttpUrl("ws://127.0.0.1:8990/ws").build(true).toUri();
WebSocketConnectionManager manager = new WebSocketConnectionManager(standardWebSocketClient, new TextWebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("Connected to the WebSocket server");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("Received message: " + message.getPayload());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("Connection closed");
}
}, "ws://127.0.0.1:8990/ws");
// 开启连接
manager.start();
}
}
1166

被折叠的 条评论
为什么被折叠?



