scaffold-websocket WebSocket 实时推送模块
模块概述
scaffold-websocket 是 Scaffold v2 平台的 WebSocket 实时推送模块,提供基于 WebSocket 的消息推送、通知分发和在线状态管理能力。模块通过自动配置机制零代码集成,智能感知 scaffold-security 模块:存在时启用 JWT 握手认证,不存在时降级为开发模式(匿名连接)。
当前为单实例会话管理(LocalWebSocketSessionManager),适用于单节点部署场景。
功能列表
- WebSocket 连接管理:基于 JWT 的握手认证
- 消息推送:单用户推送、多用户推送、全量广播
- 通知管理:发送通知、查询通知、标记已读、删除通知
- 在线状态:查询在线用户、在线数量
- 心跳机制:客户端/服务端双向心跳保活
- 消息确认:支持 ACK 确认机制
核心组件
配置与基础设施
| 类 |
说明 |
| WebSocketAutoConfiguration |
自动配置类,注册 WebSocket 端点、会话管理器、消息处理器 |
| WebSocketProperties |
配置属性(端点路径、跨域、超时等) |
| JwtHandshakeInterceptor |
JWT 握手拦截器,通过反射检测 JwtUtils 避免编译期依赖 |
| NotificationWebSocketHandler |
WebSocket 消息处理器,处理连接/断开/心跳/ACK |
会话管理
| 类 |
说明 |
| WebSocketSessionManager |
会话管理器接口(register/remove/sendToUser/broadcast/isOnline) |
| LocalWebSocketSessionManager |
本地会话管理实现,基于 ConcurrentHashMap 存储 userId -> Set |
消息模型
| 类 |
说明 |
| WebSocketMessage |
消息信封,包含 type、payload、timestamp、id |
| WebSocketMessageType |
消息类型枚举:NOTIFICATION、HEARTBEAT、HEARTBEAT_ACK、ACK |
通知业务
| 实体/类 |
说明 |
| SysNotification |
通知实体(t_sys_notification) |
| NotificationRepository |
数据访问层 |
| NotificationService |
通知服务(发送、查询、已读、删除) |
配置参数
配置前缀:scaffold.websocket
| 参数 |
类型 |
默认值 |
说明 |
| enabled |
boolean |
true |
是否启用 WebSocket 模块 |
| path |
String |
/ws |
WebSocket 端点路径 |
| allowedOrigins |
String |
* |
允许的跨域来源(逗号分隔) |
| heartbeatInterval |
long |
30000 |
心跳间隔(毫秒) |
| maxIdleTimeout |
long |
90000 |
最大空闲超时(毫秒),超时后服务端关闭连接 |
| maxSessionPerUser |
int |
5 |
单用户最大并发会话数 |
API 接口列表
通知管理(/v1/notification)
| 方法 |
路径 |
说明 |
| GET |
/list |
分页查询通知列表 |
| GET |
/unread-count |
获取未读通知数量 |
| GET |
/get/{id} |
获取通知详情 |
| POST |
/mark-read |
标记通知已读(传入 ID 列表) |
| POST |
/mark-all-read |
全部标记已读 |
| POST |
/delete/{id} |
删除通知 |
| POST |
/send-to-user |
发送通知给指定用户 |
| POST |
/send-to-users |
批量发送通知 |
| POST |
/broadcast |
广播通知给所有在线用户 |
WebSocket 端点
| 端点 |
协议 |
说明 |
| ws://{host}:{port}/api/ws |
WebSocket |
WebSocket 连接端点 |
连接参数:
- 生产模式(有 Security):通过 HTTP Header
Authorization: Bearer <token> 认证
- 开发模式(无 Security):通过 query 参数
?userId=xxx 传入用户 ID
WebSocket 消息类型
| 类型 |
方向 |
说明 |
| NOTIFICATION |
服务端 -> 客户端 |
通知消息推送 |
| HEARTBEAT |
客户端 -> 服务端 |
心跳请求 |
| HEARTBEAT_ACK |
服务端 -> 客户端 |
心跳响应 |
| ACK |
客户端 -> 服务端 |
消息确认 |
使用示例
1. 前端建立 WebSocket 连接
// 生产模式(JWT 认证)
const ws = new WebSocket('ws://localhost:8080/api/ws', [], {
headers: { 'Authorization': 'Bearer ' + token }
});
// 开发模式
const ws = new WebSocket('ws://localhost:8080/api/ws?userId=123');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'NOTIFICATION') {
console.log('收到通知:', msg.payload);
} else if (msg.type === 'HEARTBEAT_ACK') {
console.log('心跳响应');
}
};
// 发送心跳
setInterval(() => {
ws.send(JSON.stringify({ type: 'HEARTBEAT' }));
}, 30000);
2. 后端发送通知
@RequiredArgsConstructor
@Service
public class AlertService {
private final NotificationService notificationService;
private final WebSocketSessionManager sessionManager;
public void alertUser(Long userId, String title, String content) {
// 方式 1:通过 NotificationService 发送(持久化 + 实时推送)
NotificationSendDTO dto = new NotificationSendDTO();
dto.setUserId(userId);
dto.setTitle(title);
dto.setContent(content);
notificationService.sendNotification(dto);
// 方式 2:直接通过 WebSocket 推送(不持久化)
WebSocketMessage msg = WebSocketMessage.notification(Map.of(
"title", title, "content", content));
sessionManager.sendToUser(userId, msg);
}
}
3. 广播消息
notificationService.broadcast("系统维护通知", "系统将于今晚 22:00 进行维护", "SYSTEM");
SPI 扩展点
会话管理器
当前使用 LocalWebSocketSessionManager(本地内存存储)。多节点部署场景可实现 WebSocketSessionManager 接口,结合 Redis Pub/Sub 实现跨节点消息推送。
握手拦截器
通过 JwtHandshakeInterceptor 实现 JWT 认证。可自定义拦截器替换默认实现,例如集成 OAuth2 或其他认证方式。
注意事项
- 当前仅支持单实例部署(LocalWebSocketSessionManager),多节点部署需自行实现分布式会话管理
- 开发模式下(无 Security)通过 query 参数传递 userId,不进行身份验证,仅限开发环境使用
- WebSocket 连接路径为
/ws,通过 Nginx 代理时需要配置 proxy_set_header Upgrade $http_upgrade 和 proxy_set_header Connection "upgrade"
- 单用户默认最大并发会话数为 5,超出后新连接建立时旧连接会被关闭
- 心跳间隔 30 秒,空闲超时 90 秒,客户端应配合发送心跳保活