当前位置: 首页 > news >正文

WebSocket细谈

WebSocket 全景笔记(Spring 原生版)

覆盖配置、握手、收发、推送、安全、性能一条线
基于代码WebSocketConfig + WebSocketInterceptor + UnifiedWebSocketHandler


一、核心角色

组件作用
WebSocketConfig注册 URL 路径与处理器、CORS、拦截器
HandshakeInterceptor握手阶段鉴权(HTTP 层),失败直接 401
TextWebSocketHandler生命周期管理 + 业务消息路由 + 向后推送

二、配置类(总闸门)

@Configuration
@EnableWebSocket                 // ① 开启模块
public class WebSocketConfig implements WebSocketConfigurer {public void registerWebSocketHandlers(WebSocketHandlerRegistry r) {r.addHandler(unifiedHandler(), "/ws")        // 路径.addInterceptors(handshakeInterceptor())    // 鉴权.setAllowedOrigins("https://xiaoyua.com"); // 生产收窄}
}
  • 可注册 多条路径 指向同一个处理器(兼容旧版)

  • 少了 @EnableWebSocket404


三、握手拦截器(HTTP 阶段)

public class WebSocketInterceptor implements HandshakeInterceptor {boolean beforeHandshake(ServerHttpRequest req, ServerHttpResponse resp,WebSocketHandler ws, Map<String,Object> attributes){// 1. 三处取 tokenString token = req.getHeaders().getFirst("Authorization"); // Bearerif (token == null) token = extractFromSubProtocol(req);    // Sec-WebSocket-Protocolif (token == null) token = extractFromQuery(req);          // ?token=xxx// 2. 验签 → 失败直接返回 false → 浏览器收到 401,不会升级 TCPLong userId = jwtUtil.getUserIdFromToken(token);if (userId == null) return false;// 3. 把结果塞进 attributes,后续处理器随时拿attributes.put("userId", userId);return true;}
}

from 字段来源attributes.get("userId") 就是发送者无需客户端再传


四、处理器生命周期

public class UnifiedWebSocketHandler extends TextWebSocketHandler {/* 连接建立 */afterConnectionEstablished(session){Long userId = (Long) session.getAttributes().get("userId");USER_SESSIONS.put(userId, session);           // 内存快表redisTemplate.setEx("user:online:" + userId, 30min, "1");sendMessageToUser(userId, Map.of("type","connected"));}/* 收到文本消息 */handleMessage(session, TextMessage msg){Map<String,Object> data = objectMapper.readValue(msg.getPayload());switch ((String) data.get("type")){case "ping"        -> handlePing(userId);case "heartbeat"   -> handleHeartbeat(userId);case "send_message"-> handleSendMessage(userId, data); // 业务default            -> sendError(userId, "不支持类型");}}/* 连接关闭 */afterConnectionClosed(session, status){USER_SESSIONS.remove(userId);redisTemplate.delete("user:online:" + userId);}
}
  • 单线程模型 → 无需自己加锁,但禁止阻塞 IO(可扔线程池)

  • 支持部分二进制 → 重写 handleBinaryMessage


五、向后推送(任意位置可调用)

public boolean sendMessageToUser(Long userId, Object payload){WebSocketSession session = USER_SESSIONS.get(userId);if (session==null || !session.isOpen()) return false;try{String json = objectMapper.writeValueAsString(payload);session.sendMessage(new TextMessage(json));return true;}catch (IOException e){// 失败时清理无效会话,防止内存泄漏USER_SESSIONS.remove(userId);redisTemplate.delete("user:online:" + userId);return false;}
}
  • 线程安全ConcurrentHashMap + 快速失败删除

  • 失败即清理:避免“僵尸连接”占坑


六、客户端主动发私信流程(代码已实现)

  1. 前端发送

    {"type":"send_message","to_id":123,"content":"你好","temp_id":"uuid"}
  2. 处理器解析 → 调现有 MQ 业务(离线、重试、格式统一)→ 不直接推送

  3. 回包给发送者

    {"type":"message_sent","temp_id":"uuid","message_id":456,"from_user_id":789,"status":"success","timestamp":...}

    from_user_id 已补,前端可直接显示“我发的”。


七、安全与性能

话题做法
CORS生产 setAllowedOrigins("https://xxx.com")
消息大小configureWebSocketTransport(r -> r.setMaxMessageSize(512KB))
心跳保活前端每 30s 发 {type:"heartbeat"},后端刷新 Redis TTL
批量推送把 sendMessageToUser 包装成 batchSend(List<Long> userIds, payload)
集群扩容推消息时先查 Redis 在线节点,再通过 MQ 广播到对应节点再推

八、前端最小示例

const token = localStorage.getItem("token");
const ws = new WebSocket(`wss://xiaoyua.com/ws?token=${token}`);ws.onopen    = () => ws.send(JSON.stringify({type:"heartbeat"}));
ws.onmessage = (e) => {const msg = JSON.parse(e.data);if (msg.type === "private_message") {console.log(`来自 ${msg.from_user_id}: ${msg.content}`);}
};
ws.onclose   = () => console.log("断开");

九、一句话速记

“配置类注册路径,拦截器握手鉴权,处理器管生命周期,
推送调 sendMessageToUser,from 字段就是 session.getAttributes("userId")
心跳保活,失败即清理,集群用 MQ 广播!”

http://www.dtcms.com/a/449611.html

相关文章:

  • 公司网站怎么建站微网站如何做微信支付宝支付
  • Ubuntu 原地升级 MongoDB 全攻略
  • 网站变灰色代码安徽省建设工程信息网官网是什么网站
  • Hexo博客搭建系列(四):透明居中导航栏+鼠标悬停放大效果
  • 【STM32项目开源】基于STM32的智能仓库火灾检测系统
  • 陕西省建设监理协会网站证书wordpress 图片外链
  • 做模板网站企业网站类型
  • 24H2壁纸显示错误修复(针对vb.net的紧急加更)
  • 兰州做网站 东方商易怎么样做美术招生信息网站
  • 酒店客房管理系统|基于SpringBoot和Vue的酒店客房管理系统(源码+数据库+文档)
  • AI编程开发系统019-基于Vue+SpringBoot的邮件收发系统(源码+部署说明+演示视频+源码介绍+lw)
  • 做海免费素材网站排版设计模板
  • 212-基于Python的老人健康管理系统
  • 万能格式文件查看工具,支持查看图像、音视频和文档等,免安装超方便!
  • 做食品企业网站的费用wordpress文章图片全屏浏览
  • 韩国免费行情网站的推荐理由外贸 wordpress
  • 嵌入式开发核心知识点详解教程
  • 操作系统应用开发(二十六)RustDesk tls证书不匹配错误—东方仙盟筑基期
  • 如何制作个人网站住建局查询房产信息
  • 西安网站建设hyk123wordpress帖子添加代码
  • 乐理知识学习内容
  • 新手SEO教程:高效提升网站访问量的实用技巧与策略
  • 代码文件内容
  • 一款基于ESP32的导航小车
  • 自己建设网站赚钱湘潭网站建设 要选磐石网络
  • Python图形界面——TKinter
  • 深圳策划公司网站建设大型网站制作品牌
  • Django 配置与安装完整指南
  • seo网站优化方法网站建设技术指标
  • Javaweb(BeanUtils)