SpringBoot整合WebSocket实战演练

您所在的位置:网站首页 springboot开发websocket接口 SpringBoot整合WebSocket实战演练

SpringBoot整合WebSocket实战演练

2024-01-17 15:59| 来源: 网络整理| 查看: 265

前言

本文将介绍如何在Spring Boot应用程序中使用WebSocket实现服务端向客户端推送消息。Spring Boot和WebSocket的整合实现服务端向客户端推送消息,使得客户端能够实时接收并处理服务器发来的信息。WebSocket协议是一种双向通信的网络协议,使得客户端和服务器能够建立持久连接,实现实时交互。通过WebSocket,客户端可以实时接收服务器推送的消息,并立即做出响应,而不需要等待服务器处理请求。这种实时的交互方式在Web应用中非常有用,特别是在需要实时更新用户界面、处理用户输入的场景中。

一、WebSocket介绍

在介绍WebSocket之前,我们先了解传统HTTPS协议,一般客户端请求接口都是通过HTTPS协议,HTTPS是短连接,HTTPS是在TCP基础上实现的,所以建立连接需要三次握手,四次挥手,是安全可靠的,并且必须客户端主动先服务端请求,没请求一次,服务端发送一次数据。所以对于实时数据更新,或者想要服务端给客户端发送数据,就没法实现。所以就需要一种协议,客户端和服务端都可以双向发送数据,就有了WebSocket协议。

WebSocket协议是一种双向通信的网络协议,它在单个TCP连接上提供全双工通信。与HTTP请求-响应模型不同,WebSocket允许服务器和客户端在连接建立后立即进行通信,而不需要等待服务器处理请求。WebSocket协议具有以下特点:

全双工通信:WebSocket支持全双工通信,即客户端和服务器可以在同一个连接上同时发送和接收数据。持久连接:WebSocket连接是持久的,这意味着在客户端或服务器断开连接之前,它们可以保持连接状态。客户端-服务器通信:WebSocket允许客户端和服务器之间进行双向通信,这使得客户端可以实时接收并处理服务器发送的消息。

WebSocket协议的主要优势在于它的简单性和灵活性。与传统的HTTP请求-响应模型相比,WebSocket协议允许客户端和服务器更快地建立连接,并更有效地处理实时数据。

它适用于以下使用场景:

1.实时通信:WebSocket协议支持全双工通信,可以在客户端和服务器之间实时发送和接收数据,因此适用于在线聊天、实时数据更新等场景。 2.Web游戏:WebSocket协议在Web游戏开发中也很常用,可以用于实时的游戏数据交换,如游戏状态、玩家输入等。 3.在线Web应用:WebSocket协议可以用于开发实时的Web应用,如股票交易行情分析、实时新闻等。 4.数据推送:WebSocket协议可以用于服务器向客户端推送数据,如实时通知、新的消息等。

二、WebSocket常用方法以及生命周期

传统WebSocket需要重写以下方法:connect(),onOpen(),doReceive(),onMessage(),doSend(),onClose(),对于新手可能不知道,而且现在开发基本也是采用spring框架。所以本文利用Spring中的TextWebSocketHandler,TextWebSocketHandler是Spring WebSocket中用于处理基于文本的WebSocket消息的接口,它提供了一些方法来处理WebSocket会话的各个阶段,使用只要继承TextWebSocketHandler类就行。下面是TextWebSocketHandler常用的方法和流程:

afterConnectionEstablished():当客户端建立连接时调用,用于执行连接建立后的操作。handleTextMessage():当接收到消息时调用,用于处理客户端发送的消息。handleTransportError():当连接发生错误时调用,用于处理连接错误。afterConnectionClosed():当连接关闭时调用,用于执行连接关闭后的操作。

以下是TextWebSocketHandler实例:

@Component public class WebSocketHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 连接建立后执行的操作 System.out.println("Connection established: " + session.getId()); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理接收到的消息 System.out.println("Received message: " + message.getPayload()); // 向客户端发送响应 session.sendMessage(new TextMessage("Hello, client!")); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { // 处理连接错误 exception.printStackTrace(); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { // 连接关闭后执行的操作 System.out.println("Connection closed: " + session.getId()); } }

TextWebSocketHandle生命周期,包括客户端和服务端,客户端使用WebSocketSession与客户端建立连接,服务端客户端都可以调用WebSocketSession对象,包括关闭连接close,服务端调用sendMessage方法发送消息,具体如图所示:

三、SpringBoot整合WebSocket

上面我们简单介绍了WebSocket的以及TextWebSocketHandle的生命周期,接下来,我们就可以利用Springboot整合WebSocket了。

1.引入WebSocket依赖

主要是引入websocket依赖

org.springframework.boot spring-boot-starter-websocket 2.新增websocket配置WebSocketConfig

新增配置类,实现WebSocketConfigurer ,主要配置websocket的注册连接地址,客户端连接ws://ip:端口/websocket/game,就会连接到改socket

@Component @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private WebSocketHandler webSocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler, "/websocket/game") .addInterceptors(new WebSocketInterceptor()); } }3.新增websocket处理器WebSocketHandler

WebSocketHandler就是监听websocket连接之后的操作,也是上面继承的TextWebSocketHandle,并且根据上面的什么周期,我们只要在原有的基础上进行业务处理就行了,本文模拟玩游戏,客户端连接之后,服务端扣减用户试玩的时长,当时长没有了服务端主动推送websocket消息给客户端,断开连接。具体代码如下:

@Component public class WebSocketHandler extends TextWebSocketHandler implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(WebSocketHandler.class); // 连接列表 private static Map sessionCache = new HashMap(); // 定时任务 private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); @Override public void afterPropertiesSet() throws Exception { // 定时任务 scheduler.scheduleAtFixedRate(() -> { try { // 扣减时长 deduct(); } catch (Exception e) { } }, 30,60, TimeUnit.SECONDS); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 连接建立后执行的操作 System.out.println("连接成功: " + session.getId()); // 放到缓存连接列表 Map attributes = session.getAttributes(); Object objUid = attributes.get("uid"); String uid = objUid.toString(); sessionCache.put(uid, session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理接收到的消息 System.out.println("服务端接收消息: " + message.getPayload()); // 向客户端发送响应 sendMessage(session,"Hello, client!"); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { // 处理连接错误 exception.printStackTrace(); closeSession(session,"关闭连接"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { // 连接关闭后执行的操作 closeSession(session,"关闭连接"); // 删除缓存连接列表 Map attributes = session.getAttributes(); Object objUid = attributes.get("uid"); String uid = objUid.toString(); sessionCache.remove(uid); } /** * 发送消息 * @param session * @param message */ private void sendMessage(WebSocketSession session, String message) { if (session != null && session.isOpen()) { try { session.sendMessage(new TextMessage(message)); } catch (IOException e) { e.printStackTrace(); } } } private void closeSession(WebSocketSession session, String message) { if (message != null) { sendMessage(session, message); } try { if (session.isOpen()) { session.close(); } } catch (IOException e) { e.printStackTrace(); } } private void deduct() { // todo 业务处理。。。。 String uid = "123"; WebSocketSession session = sessionCache.get(uid); sendMessage(session, "扣减时长"); } }四、在线测试

websocket协议调用调试跟HTTP不一样,不能直接用浏览器调用,推荐在线小工具调试:WebSocket在线测试_在线模拟websocket请求工具

启动springboot工程服务,在调试工具输入地址:ws://localhost:8080/websocket/game?uid=123

调试工具模拟客户端先服务端发送消息:

由于我们模拟了扣减游戏时长,会发现,服务端有定时任务,每个60s扣取时长,并且发送消息通知客户端:

以上就完成websocket的整合,算是比较简单,但是如果需要结合业务处理,就有很多细节要调整了,

五、关于WebSocket的细节处理1.WebSocket资源分配问题

由于websocket连接,其实是生成一个长连接在内存中,如果用户连接过多的话,可能会造成资源不足,所以在实际业务处理中,一般会设置连接大小,或者其他分配介质,如果超过了,就有放到队列中进行等待操作。

2.WebSocket连接心跳问题

WebSocket维护心跳是必要的,因为它可以保持连接的活性,防止连接超时断开,并确保实时消息传输。并且对于长时间没有心跳的连接要及时断开,防止占用内存。一般通过约定协议,定时客户端向服务端发送消息,将消息的标识存在到缓存,设定一定的时间,服务端每次接收到客户端心跳消息,就更新缓存时间,这样缓存就一直存在,否则,服务端将断开连接。可以使用本地缓存caffeine或者redis缓存。

总结

本文主要讲解了SpringBoot月websocket的实战,但是对于websocket的使用也是有优缺点的。

优点:整合了SpringBoo的WebSocket可以提供更加灵活和强大的实时通信功能。开发者可以快速实现实时通信、在线协作等功能,减少了开发时间和代码复杂度。同时,WebSocket的双向通信能力可以实现服务器主动推送数据,提高了应用程序的实时性和响应速度。

缺点:WebSocket是基于TCP的协议,相对于HTTP的短连接,它需要更多的网络资源和计算资源。同时,由于WebSocket连接的长时间保持,如果大量用户同时连接服务器,可能会对服务器造成较大压力。此外,WebSocket的协议相对复杂,开发者需要额外学习。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3