WebSocket
WebSocket 是一种计算机通信协议,用于在Web应用程序中实现双向通信。它允许服务器和客户端之间建立持久连接,并且可以通过单个网络套接字进行全双工通信。与传统的HTTP请求-响应模型不同,WebSocket 使用事件驱动的模式,可以实时地在服务器和客户端之间传输数据。
WebSocket 协议的特点包括:
- • 建立持久连接:WebSocket 连接在创建后保持打开状态,而不需要每次通信都重新建立连接。这降低了通信的延迟和资源消耗。
- • 全双工通信:服务器和客户端可以同时发送和接收数据,实现真正的双向通信。这使得服务器可以主动推送数据给客户端,而不仅仅是在请求时响应数据。
- • 低延迟:由于 WebSocket 连接始终保持打开状态,消息的传输延迟较小。这对于实时应用程序(如聊天应用、股票市场数据等)非常重要。
- • 跨域支持:WebSocket 协议支持跨域通信,即在不同域名或端口的服务器之间进行通信。
WebSocket 在 Web 应用程序中有广泛的应用,例如实时聊天应用、在线游戏、股票市场数据推送、在线协作等。它提供了一种更高效、实时的通信方式,同时减少了服务器和客户端之间的网络负载。
SpringBoot 整合 WebSocket
添加依赖
代码语言:javascript复制<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
WebSocketServer
代码语言:javascript复制package com.demo.websocket;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @ClassName: WebSocketServer.java
* @ClassPath: com.demo.websocket.WebSocketServer.java
* @Description: WebSocket
* @Author: tanyp
* @Date: 2023-09-05 10:35
**/
@Slf4j
@ServerEndpoint("/ws/{id}")
@Component
public class WebSocketServer {
public static CopyOnWriteArraySet<WebSocketServer> sessionSet = new CopyOnWriteArraySet<>();
private Session session;
@Getter
private String id;
@OnOpen
public void onOpen(Session session, @PathParam("id") String id) {
log.info("=======WebSocket 建立连接 id:{}==============", id);
this.session = session;
this.id = id;
sessionSet.add(this);
}
@OnClose
public void onClose() {
sessionSet.remove(this);
}
@OnError
public void onError(Session session, Throwable error, @PathParam("id") String id) {
log.error("========websocket错误================");
error.printStackTrace();
if (StringUtils.isNotBlank(id)) {
for (WebSocketServer ws : sessionSet) {
if (ws.id.equals(id)) {
sessionSet.remove(ws);
}
}
}
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public synchronized static void sendMessage(@PathParam("id") String id, String message) throws IOException {
if (StringUtils.isNotBlank(id)) {
for (WebSocketServer ws : sessionSet) {
if (ws.id.equals(id)) {
ws.sendMessage(message);
}
}
}
}
}
推送数据
代码语言:javascript复制// websocket 推送数据
String prefix = "test-"; // 前缀
String sequence = "u0001"; // 唯一序列,例如:用户ID
String json = JSON.toJSONString({}); // JSON 数据
try {
WebSocketServer.sendMessage(prefix sequence, json);
} catch (Exception e) {
log.error("websocket 推送数据异常:{}", e);
}
Vue3 使用 WebSocket
代码语言:javascript复制<script setup lang="ts">
import { onMounted, reactive,toRefs } from 'vue'
const state = reactive({
socket: null,
})
const {socket} = toRefs(state)
onMounted(()=>{
webSocket()
})
function webSocket(){
if ('WebSocket' in window) {
// 与后端配置保持一致(IP 端口 "/ws/" 前缀 唯一序列)
state.socket = new WebSocket('ws:' window.location.hostname ':8080/ws/test-u0001');
state.socket.onmessage = function (event:any) {
// 接收数据,更具业务自行处理
console.log(event.data)
}
state.socket.onopen = function () {
console.log('连接已建立')
}
state.socket.onclose = function () {
console.log('连接已关闭')
}
state.socket.onerror = function () {
console.log('连接异常,尝试重新连接')
// webSocket();
}
window.onbeforeunload = function () {
state.socket.onclose();
}
}
}
</script>
注:一定确保 WebSocket 连接的地址与后端配置的地址相匹配(IP 端口 "/ws/" 前缀 唯一序列)。例如:http://127.0.0.1:8080/ws/test-u0001