Files
blog-press/docs/Web/SpringBoot/SpringBoot-WebSocket.md

154 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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("*");
}
}
```
&emsp;&emsp;WebSocket连接地址ip:port/ws?userId=123。
# 四、前端使用
&emsp;&emsp;参考:[useWebSocket](../Vue/VueUse.md)