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_upgradeproxy_set_header Connection "upgrade"
  • 单用户默认最大并发会话数为 5,超出后新连接建立时旧连接会被关闭
  • 心跳间隔 30 秒,空闲超时 90 秒,客户端应配合发送心跳保活