SpringBoot + WebSocket 实现实时消息推送(在线聊天/通知)

发布时间:2026/6/19 3:58:54
SpringBoot + WebSocket 实现实时消息推送(在线聊天/通知) WebSocket 是实现服务端主动推送消息的常用技术适用于在线聊天、系统通知、实时数据展示等场景。本文从零搭建一个 SpringBoot WebSocket 的实时消息推送系统。一、WebSocket 是什么传统 HTTP 通信只能由客户端发起请求服务端被动响应。WebSocket 建立连接后服务端可以主动向客户端推送消息。对比HTTPWebSocket通信方向客户端→服务端双向通信连接方式每次请求新建连接建立连接后保持实时性需要轮询即时推送适用场景普通 API聊天、通知、实时数据二、SpringBoot 整合 WebSocket1. 引入依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId/dependency2. 配置 WebSocketConfigurationpublicclassWebSocketConfig{BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}三、核心WebSocket 服务端ComponentServerEndpoint(/ws/{userId})Slf4jpublicclassWebSocketServer{/** 存放每个用户的 WebSocket 连接 */privatestaticMapString,SessionsessionMapnewConcurrentHashMap();/** * 连接建立成功 */OnOpenpublicvoidonOpen(Sessionsession,PathParam(userId)StringuserId){sessionMap.put(userId,session);log.info(用户 {} 已连接当前在线人数: {},userId,sessionMap.size());}/** * 连接关闭 */OnClosepublicvoidonClose(PathParam(userId)StringuserId){sessionMap.remove(userId);log.info(用户 {} 已断开当前在线人数: {},userId,sessionMap.size());}/** * 收到客户端消息 */OnMessagepublicvoidonMessage(Stringmessage,PathParam(userId)StringuserId){log.info(收到用户 {} 的消息: {},userId,message);}/** * 发生错误 */OnErrorpublicvoidonError(Sessionsession,Throwableerror){log.error(WebSocket 错误,error);}/** * 向指定用户推送消息 */publicstaticvoidsendToUser(StringuserId,Stringmessage){SessionsessionsessionMap.get(userId);if(session!nullsession.isOpen()){try{session.getBasicRemote().sendText(message);}catch(IOExceptione){log.error(推送消息失败,e);}}}/** * 向所有用户广播消息 */publicstaticvoidbroadcast(Stringmessage){sessionMap.values().forEach(session-{try{session.getBasicRemote().sendText(message);}catch(IOExceptione){log.error(广播消息失败,e);}});}/** * 获取在线用户数 */publicstaticintgetOnlineCount(){returnsessionMap.size();}}四、服务端主动推送消息在 Controller 中调用 WebSocket 推送消息RestControllerRequestMapping(/push)publicclassPushController{/** * 推送给指定用户 */PostMapping(/user/{userId})publicResultVOpushToUser(PathVariableStringuserId,RequestBodyStringmessage){WebSocketServer.sendToUser(userId,message);returnResultVO.success(推送成功);}/** * 广播给所有用户 */PostMapping(/broadcast)publicResultVObroadcast(RequestBodyStringmessage){WebSocketServer.broadcast(message);returnResultVO.success(广播成功);}/** * 获取在线人数 */GetMapping(/online)publicResultVOgetOnlineCount(){returnResultVO.success(WebSocketServer.getOnlineCount());}}五、前端页面连接 WebSocket!DOCTYPEhtmlhtmlheadmetacharsetUTF-8titleWebSocket 消息推送/title/headbodyh3WebSocket 实时消息/h3divinputtypetextiduserIdplaceholder用户IDvalueuser001buttononclickconnect()连接/buttonbuttononclickdisconnect()断开/button/divdivstylemargin-top:10px;dividmessagesstyleborder:1px solid #ccc;height:300px;overflow-y:scroll;padding:10px;/div/divscriptletwebsocketnull;functionconnect(){constuserIddocument.getElementById(userId).value;websocketnewWebSocket(ws://localhost:8080/ws/userId);websocket.onopenfunction(){appendMessage(✅ 连接成功用户ID: userId);};websocket.onmessagefunction(event){appendMessage( 收到消息: event.data);};websocket.onclosefunction(){appendMessage(❌ 连接已断开);};websocket.onerrorfunction(error){appendMessage(⚠️ 连接出错);};}functiondisconnect(){if(websocket){websocket.close();}}functionappendMessage(msg){constdivdocument.getElementById(messages);div.innerHTMLdivmsg/div;div.scrollTopdiv.scrollHeight;}/script/body/html六、实战系统通知推送实际项目中在业务代码中调用推送ServicepublicclassOrderService{publicvoidcreateOrder(Orderorder){// 1. 保存订单orderMapper.insert(order);// 2. 推送通知给用户JSONObjectmsgnewJSONObject();msg.put(type,order_notify);msg.put(orderId,order.getId());msg.put(message,您的订单已创建成功);WebSocketServer.sendToUser(order.getUserId().toString(),msg.toJSONString());}}客户端收到消息后根据type字段做相应处理websocket.onmessagefunction(event){constdataJSON.parse(event.data);if(data.typeorder_notify){showNotification( data.message);}elseif(data.typesystem_notify){showNotification( data.message);}};七、常见问题1. WebSocket 连接被拦截如果项目中有拦截器需要放行 WebSocket 请求registry.addInterceptor(loginInterceptor).addPathPatterns(/**).excludePathPatterns(/ws/**);// 放行 WebSocket2. 跨域问题BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}// WebSocket 原生不支持跨域配置// SpringBoot 方式需要在配置中添加BeanpublicWebSocketConfigurerwebSocketConfigurer(){returnregistry-registry.addHandler(webSocketHandler(),/ws/{userId}).setAllowedOrigins(*);}3. 心跳保活WebSocket 长时间空闲可能被断开定期发送心跳包// 客户端每 30 秒发送心跳setInterval((){if(websocketwebsocket.readyStateWebSocket.OPEN){websocket.send(ping);}},30000);总结WebSocket 是实时消息推送的首选方案。SpringBoot 整合 WebSocket 非常简单三步走引入依赖配置编写 WebSocketServer—— OnOpen、OnClose、OnMessage业务代码调用推送—— 面向指定用户或广播如果对你有帮助欢迎点赞、评论、关注【张老师技术栈】持续分享 Java/Python/爬虫 实战干货。