154 lines
4.3 KiB
Markdown
154 lines
4.3 KiB
Markdown
---
|
||
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) |