因为http 通信只能由客户端发起,服务器返回查询结果,HTTP 协议做不到服务器主动向客户端推送信息, 服务器有连续的状态变化,客户端要获知就非常麻烦。 我们只能使用轮询:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。 轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开);
websocket介绍
WebSocket是一种在单个TCP连接上提供全双工通信的协议,它允许客户端和服务器之间进行实时数据传输。与传统的HTTP通信方式不同,WebSocket允许服务器主动向客户端推送数据,而不需要客户端先发起请求。
特点和优势:
-
全双工通信:WebSocket允许客户端和服务器之间同时发送和接收数据,支持实时性更强的应用场景,如在线聊天、实时通知等。
-
更低的延迟:与轮询和长轮询相比,WebSocket减少了每个消息的头部开销,提供了更低的延迟。
-
节省带宽和服务器资源:WebSocket连接建立后,客户端和服务器之间的通信通过较少的控制开销和更高的吞吐量进行,节省了带宽和服务器资源。
-
支持跨域通信:WebSocket可以通过浏览器的标准API实现跨域通信,提供了更加安全和便捷的方式。
maven依赖: <dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1<[胜利]ersion> </dependency>
前端初始化工作代码
initWebSocket() { // 获取当前页面的协议、主机和端口 const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const host = window.location.host; const endpoint = '/websocket_war/echo'; // 动态生成 WebSocket 的 URL const wsUrl = `${protocol}//${host}${endpoint}`; console.log(wsUrl); // 创建 WebSocket 连接 var ws = new WebSocket(wsUrl); ws.onopen = function () { console.log('WebSocket 连接已经建立。'); // ws.send('Hello, server!'); }; ws.onmessage = function (event) { console.log('收到服务器消息:', event.data); }; ws.onerror = function (event) { console.error('WebSocket 连接出现错误:', event); }; ws.onclose = function () { console.log('WebSocket 连接已经关闭。'); }; window.onbeforeunload = function() { app.$data.ws.close(); }; this.ws = ws; }
后端代码
import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; @ServerEndpoint("/echo") public class AdminEchoServer { private static Session session; @OnOpen public void onOpen(Session session) { System.out.println("WebSocket 连接已经建立。"); AdminEchoServer.session = session; } @OnMessage public void onMessage(String message, Session session) throws IOException { System.out.println("收到客户端消息:" + message); //session.getBasicRemote().sendText("服务器收到消息:" + message); } @OnClose public void onClose() { System.out.println("WebSocket 连接已经关闭。"); } @OnError public void onError(Throwable t) { System.out.println("WebSocket 连接出现错误:" + t.getMessage()); } public void send(String message) throws IOException { session.getBasicRemote().sendText(message); } }
建议将聊天的内容存储到redis中的有序集合中,利用时间戳作为有序集合的分数