SpringBoot、Vue3 整合 WebSocket

2023-09-13 20:02:04 浏览数 (1)

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

0 人点赞