feat
This commit is contained in:
154
docs/Web/SpringBoot/SpringBoot-WebSocket.md
Normal file
154
docs/Web/SpringBoot/SpringBoot-WebSocket.md
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
title: SpringBoot WebSocket使用
|
||||
date: 2026-06-08
|
||||
---
|
||||
|
||||
# 一、简介
|
||||
  [WebSocket API](https://docs.springjava.cn/spring-framework/reference/web/websocket/server.html)
|
||||
|
||||
# 二、安装
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
# 三、使用
|
||||
## 3.1 定义WebSocketHandler
|
||||
```java
|
||||
@Component
|
||||
public class GenericWebSocketHandler extends TextWebSocketHandler {
|
||||
private static final Map<String, WebSocketSession> SESSION_MAP =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
String userId = getUserId(session);
|
||||
SESSION_MAP.put(userId, session);
|
||||
log("用户连接成功:" + userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
String userId = getUserId(session);
|
||||
SESSION_MAP.remove(userId);
|
||||
log("用户断开连接:" + userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
|
||||
String payload = message.getPayload();
|
||||
|
||||
// 心跳处理
|
||||
if ("PING".equalsIgnoreCase(payload)) {
|
||||
session.sendMessage(new TextMessage("PONG"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 普通消息(可按 JSON 协议扩展)
|
||||
log("收到消息:" + payload);
|
||||
session.sendMessage(new TextMessage("服务端已收到:" + payload));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
log("传输异常:" + exception.getMessage());
|
||||
}
|
||||
|
||||
/** 从 session 中获取用户标识(握手阶段放入) */
|
||||
private String getUserId(WebSocketSession session) {
|
||||
return (String) session.getAttributes().getOrDefault("userId", session.getId());
|
||||
}
|
||||
|
||||
/** 单发 */
|
||||
public void sendToUser(String userId, String msg) throws IOException {
|
||||
WebSocketSession session = SESSION_MAP.get(userId);
|
||||
if (session != null && session.isOpen()) {
|
||||
session.sendMessage(new TextMessage(msg));
|
||||
}
|
||||
}
|
||||
|
||||
/** 广播 */
|
||||
public void broadcast(String msg) throws IOException {
|
||||
for (WebSocketSession session : SESSION_MAP.values()) {
|
||||
if (session.isOpen()) {
|
||||
session.sendMessage(new TextMessage(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 在线人数 */
|
||||
public int onlineCount() {
|
||||
return SESSION_MAP.size();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.2 定义HandshakeInterceptor
|
||||
```java
|
||||
@Component
|
||||
public class GenericHandshakeInterceptor implements HandshakeInterceptor {
|
||||
|
||||
/**
|
||||
* 握手前执行
|
||||
*/
|
||||
@Override
|
||||
public boolean beforeHandshake(
|
||||
ServerHttpRequest request,
|
||||
ServerHttpResponse response,
|
||||
WebSocketHandler wsHandler,
|
||||
Map<String, Object> attributes) {
|
||||
// 从请求中URL中获取id
|
||||
// 例如:ws://localhost:8080/ws?userId=123,多个参数用&连接
|
||||
String userId = servletRequest.getServletRequest().getParameter("userId");
|
||||
|
||||
if (userId == null) {
|
||||
// 返回 false → 握手失败 → 连接被拒绝
|
||||
return false;
|
||||
}
|
||||
|
||||
// 放入 attributes 中,方便下次获取
|
||||
attributes.put("userId", userId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 握手完成后执行(一般不用写)
|
||||
*/
|
||||
@Override
|
||||
public void afterHandshake(
|
||||
ServerHttpRequest request,
|
||||
ServerHttpResponse response,
|
||||
WebSocketHandler wsHandler,
|
||||
Exception exception) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.3 配置WebSocketConfigurer
|
||||
```java
|
||||
@Configuration
|
||||
@EnableWebSocket
|
||||
public class WebSocketConfig implements WebSocketConfigurer {
|
||||
|
||||
@Resource
|
||||
private GenericWebSocketHandler genericWebSocketHandler;
|
||||
|
||||
@Resource
|
||||
private GenericHandshakeInterceptor genericHandshakeInterceptor;
|
||||
|
||||
@Override
|
||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||
registry.addHandler(genericWebSocketHandler, "/ws")
|
||||
.addInterceptors(genericHandshakeInterceptor)
|
||||
.setAllowedOrigins("*");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
  WebSocket连接地址:ip:port/ws?userId=123。
|
||||
|
||||
# 四、前端使用
|
||||
  参考:[useWebSocket](../Vue/VueUse.md)
|
||||
Reference in New Issue
Block a user