springboot websocket 推送?websocket接口后端怎么调用
大家好,今天来为大家分享springboot websocket 推送的一些知识点,和websocket接口后端怎么调用的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
SpringBoot整合websocket实现群聊
SpringBoot整合WebSocket实现群聊的完整方案如下:
一、核心实现思路服务端推送:客户端连接后,服务端通过@ServerEndpoint注解暴露WebSocket端点会话管理:使用ConcurrentHashMap维护所有活跃会话消息广播:收到消息后遍历所有会话进行推送生命周期管理:通过@OnOpen/@OnClose处理连接建立和关闭二、环境配置1.添加依赖(pom.xml)<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version></parent><dependencies><!-- WebSocket支持--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!--工具类--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency></dependencies>2. WebSocket配置类@Configurationpublic class WebSocketConfig{@Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter();}}三、核心代码实现1. WebSocket端点处理类@Slf4j@Controller@ServerEndpoint("/chat")//访问路径为 ws://localhost:8080/chatpublic class WebSocketServer{//静态变量维护所有会话 private static final ConcurrentHashMap<String, Session> SESSION_POOL= new ConcurrentHashMap<>();@OnOpen public void onOpen(Session session){ SESSION_POOL.put(session.getId(), session); broadcast(session.getId()+"加入群聊"); log.info("新连接加入:{}", session.getId());}@OnMessage public void onMessage(String message, Session session){ log.info("收到消息:{}", message); broadcast("用户"+ session.getId()+":"+ message);}@OnClose public void onClose(Session session){ SESSION_POOL.remove(session.getId()); broadcast(session.getId()+"退出群聊"); log.info("连接关闭:{}", session.getId());}@OnError public void onError(Throwable error, Session session){ log.error("发生异常", error);}//广播消息 private static void broadcast(String message){ SESSION_POOL.forEach((id, session)->{ try{ session.getBasicRemote().sendText(message);} catch(IOException e){ log.error("广播消息失败", e);}});}}2.工具类优化版(可选)public class WebSocketUtil{ private static final ConcurrentHashMap<String, Session> SESSIONS= new ConcurrentHashMap<>();//添加会话 public static void add(Session session){ SESSIONS.put(session.getId(), session);}//移除会话 public static void remove(Session session){ SESSIONS.remove(session.getId());}//广播消息 public static void broadcast(String message){ SESSIONS.forEach((id, session)->{ try{ if(session.isOpen()){ session.getAsyncRemote().sendText(message);}} catch(Exception e){ log.error("发送失败:{}", e.getMessage());}});}}四、前端测试代码<!DOCTYPE html><html><head><title>WebSocket测试</title></head><body><div id="messages"></div><input type="text" id="messageInput" placeholder="输入消息"><button onclick="sendMessage()">发送</button><script> const socket= new WebSocket("ws://localhost:8080/chat"); socket.onopen=()=> console.log("连接成功"); socket.onmessage=(e)=>{ document.getElementById("messages").innerHTML+= `<p>${e.data}</p>`;}; function sendMessage(){ const input= document.getElementById("messageInput"); socket.send(input.value); input.value="";}</script></body></html>五、关键点说明路径配置:@ServerEndpoint注解值即为WebSocket连接路径并发安全:使用ConcurrentHashMap保证多线程环境下的会话管理安全异步发送:推荐使用getAsyncRemote()替代getBasicRemote()避免阻塞连接监控:可通过session.isOpen()检查连接状态六、测试验证启动SpringBoot应用访问打开多个测试页面在任意页面输入消息,观察所有页面同步显示
七、扩展建议添加用户认证(通过URL参数或HandshakeInterceptor)实现私聊功能(维护用户ID与Session的映射)增加心跳机制检测连接状态使用消息对象替代纯文本(定义Message类包含type/content等字段)通过以上实现,即可完成一个基础的SpringBoot+WebSocket群聊系统。
SpringBoot - WebSocket
websocket是一种网络通信协议,类似 http协议
Http协议有一个缺陷:通信只能由客户端发起
在某种场景下,例如,在外卖场景下,骑手位置更新时,服务器端向客户端发送骑手位置。如果使用 http协议,那么就只能轮询了,由客户端不停地向服务器端发送请求,获取骑手的位置。
轮询的效率低下,有一定的延迟性,并且频繁的发送请求也会造成资源的浪费。
使用 WebSocket协议可以实现由服务器端主动向客户端推送消息,当然客户端也可以向服务器端发送消息。
这里仅介绍利用 Spring框架使用 WebSocket的方式,原因:Spring使用 WebSocket简便且易于扩展。
SpringBoot使用 WebSocket非常方便,依赖上仅需要添加相应的 Starter即可。
先给出概要的开发步骤:
其实到这里,基础的 websocket服务已经搭建好了,剩下的可以自己在 handler与 interceptor中写自己的业务逻辑了
前端页面:
先启动服务器端 SpringBoot应用,再使用前端页面点击测试一下就 ok了
实战spring-boot-starter-websocket之断网心跳续期实践
业务中需要应用到Websocket长连接进行数据传输,由于服务使用的是Zuul1.0版本,对ws协议支持较弱,后续尝试使用了 spring-boot-starter-websocket来完成的。关于怎么集成的话网上有非常多的文章了,我就不多费口舌了。
我们目前实现的功能是可以通过WebSocket调用接口发送埋点,另外还需要监听用户离开的事件为这个埋点画上一个终止访问时间。目前测试下场景有:
前4点触发了任意操作,服务端都会监听到 DISCONNECT离开事件。但是第5点直接断网,服务端竟然是无感知的,这个时候产生的问题就是客户断网了,服务端是认为在线的,如果不重新联网登录的话,那么这个用户将会一直一直在线,埋点会一直计算。完了个蛋~
至于为什么断网之后,ws会认为他是在线的,可能管道打开了之后由于断网导致断开时间发送不出去吧。
我目前能够想到比较简单的办法就是:心跳续约
捋清了思路,大概就知道如何做了。
然后特意看了下 spring-boot-starter-websocket的源码,发现其实他有提供此功能。
先说下如何实现:
我们是在在实现了 DelegatingWebSocketMessageBrokerConfiguration的配置类中重写 configureMessageBroker方法。
比较关键就是 setTaskScheduler和 setHeartbeatValue一个负责调度、一个负责配置间隔。
这俩要么都填要么都不填。
配置了这俩参数之后,服务启动的时候会触发一个 HeartbeatTask线程来专门维持心跳。
我们可以看看他的流程是如何运转的。
核心任务调度类: org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.HeartbeatTask
服务端在启动的时候 SimpleBrokerMessageHandler在初始化完成之后会回调 start的方法,然而他会触发一个 startInternal开始调度任务,判断依据就是有没有配置 TaskScheduler(对应的就是配置类中的setTaskScheduler),一旦启动之后,会根据你给的心跳数组 serverHeartbeat,来选择调度时间。
org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler
检测心跳、超过间隔则剔除、并且定期回写心跳给客户端。
还有一点需要注意的是读的间隔时间:
假设用户网络不好,心跳漏发了一次,这个时候如果按照本次的逻辑而言,该用户的最后心跳时间肯定会超时。而它的做法是,将设定的读超时时间 3,就相当于有3次机会*。
这个在创建session的时候 SessionInfo里面就已经做好了处理:
org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.SessionInfo#SessionInfo
所以这个时候,你可能需要根据业务能够接受的时长去配置,也别忘了这个事。
还有很关键的一点就是让客户端的心跳发送间隔和服务端尽可能保持一致,不然有可能出现莫名其妙的下线情况,尽可能还是在这种地方加好日志。
好了,希望在遇到断网问题的时候,能够帮助到你。
如果有疑问请留言,我会尽快答复。
好了,关于springboot websocket 推送和websocket接口后端怎么调用的问题到这里结束啦,希望可以解决您的问题哈!