当前位置: 首页 > news >正文

Java - WebSocket配置及使用

引入依赖

Spring Boot 默认支持 WebSocket,但需要引入 spring-boot-starter-websocket 依赖,然后重新构建项目

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

搭建 WebSocket 服务

创建 WebSocketServer.java

package com.project.module.webSocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@ServerEndpoint("/ws/{userId}") // WebSocket 连接端点
public class WebSocketServer {

    // 存储所有用户的 WebSocket 连接
    private static final Map<String, WebSocketServer> clients = new ConcurrentHashMap<>();
    private Session session;
    private String userId; // 当前连接的用户ID

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        clients.put(userId, this);
        System.out.println("新客户端连接,当前在线用户:" + clients);
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println("收到消息:" + message);

        // 假设消息格式是 "userId:message"
        String[] parts = message.split(":", 2);
        if (parts.length == 2) {
            String targetUserId = parts[0];
            String msg = parts[1];

            sendToUser(targetUserId, "私信:" + msg);
        } else {
            System.out.println("无效的消息格式:" + message);
        }
    }

//    @OnMessage
//    public void onMessage(String message, @PathParam("userId") String userId) {
//        System.out.println("收到消息:" + message);
//        sendToUser(userId, "私信:" + message);
//    }

    // 给指定用户发送消息
    public void sendToUser(String userId, Object messageObject) {
        WebSocketServer client = clients.get(userId);
        System.out.println("当前用户:" + userId);
        if (client != null) {
            try {
                // 使用 Jackson 转换对象为 JSON
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonMessage = objectMapper.writeValueAsString(messageObject);
                client.session.getBasicRemote().sendText(jsonMessage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("用户 " + userId + " 不在线,消息未发送");
        }
    }

    @OnClose
    public void onClose() {
        for (Map.Entry<String, WebSocketServer> entry : clients.entrySet()) {
            if (entry.getValue().session.getId().equals(session.getId())) {
                clients.remove(entry.getKey());
                System.out.println("客户端断开连接,当前在线人数:" + clients.size());
                break;
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendToAll(Object messageObject) {
        for (Map.Entry<String, WebSocketServer> entry : clients.entrySet()) {
            WebSocketServer client = entry.getValue();
            try {
                // 使用 Jackson 转换对象为 JSON
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonMessage = objectMapper.writeValueAsString(messageObject);
                client.session.getBasicRemote().sendText(jsonMessage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public Map<String, WebSocketServer> getClients() {
        return clients;
    }
}

手动注册 WebSocket

@ServerEndpoint 不能直接用 @Autowired 注入 Spring Bean,所以需要 手动注册
在 WebSocketConfig 里添加 Bean
创建 WebSocketConfig.java

package com.project.module.webSocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    
    // 启动 WebSocket 服务器
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

发送Websocket服务

package com.project.module.webSocket;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class WebSocketTask {

    private final WebSocketServer webSocketServer;

    public WebSocketTask(WebSocketServer webSocketServer) {
        this.webSocketServer = webSocketServer;
    }

    // 每一分钟推送一次消息
    @Scheduled(fixedRate = 1000*60)
    public void pushMessage() {
        webSocketServer.sendToUser("userId","定时任务推送消息:" + System.currentTimeMillis());
    }
}

前端链接 WebSocket

创建 webSocket.js
注:此处的 import {host} from './base.js'为引入的全局服务地址,例如 host 为 localhost ,开发者可自行更换为自己的 WebSocket 地址

import {host} from './base.js'
const WebSocketService = {
    ws: null,
    connect(userId, callback) {
        this.ws = new WebSocket(`ws://${host}:8980/ws/` + userId);

        this.ws.onopen = () => {
            console.log("WebSocket 连接成功");
        };

        this.ws.onmessage = (event) => {
            callback(JSON.parse(event.data));
        };

        this.ws.onclose = () => {
            console.log("WebSocket 连接已关闭");
        };
    },
    sendMessage(message) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(message);
        }
    },
    disconnect() {
        if (this.ws) {
            this.ws.close();
        }
    },
};

export default WebSocketService;

在Vue组将中使用

<template>
  <div class="container">
  </div>
</template>

<script setup>
import { onMounted, ref } from "vue";
import WebSocketService from "@/utils/websocket";

const CURRENT_CHART_NAME = 'safety'
const safetyRef = ref()
let safetyChart = null

const { setChart } = useSetChart()

onMounted(() => {
  websocketConn()
})

function websocketConn() {
  const userId = `userId`
  WebSocketService.connect(userId, (msg) => {
    console.log(msg)
  });
}
</script>

注:此处的userId对应后端 webSocketServer.sendToUser("userId ","定时任务推送消息:" + System.currentTimeMillis()); 中的 userId,代表前端订阅WebSocket消息的用户以及WebSocket要发送的用户

http://www.dtcms.com/a/109589.html

相关文章:

  • Dart 语法
  • 【Tauri2】013——前端Window Event与创建Window
  • 搭建环境-opencv-qt
  • 震源车:震源激发平板模态分析
  • 使用python实现视频播放器(支持拖动播放位置跳转)
  • 第二十六章:Seaborn库实现统计数据可视化
  • 2025年机动车授权签字人考试判断题分享
  • 2025年渗透测试面试题总结- 某汽车厂商-安全工程师扩展(题目+回答)
  • 量子计算与经典计算的融合与未来
  • AI赋能——让人工智能助力工作提质增效
  • CVPR2024 | 构建时序动作检测模型对时序干扰的鲁棒性基准
  • 近日八股——计算机网络
  • 使用pycharm社区版调试DIFY后端python代码
  • 破解 N 皇后 II:位运算的高效艺术
  • 4月3日工作日志
  • CVSS-通用漏洞评分系统版本 4.0:规范文档
  • 代码随想录|动态规划|18完全背包理论基础
  • Java Lambda 表达式提升效率
  • 高效深度学习lecture01
  • Flask与 FastAPI 对比:哪个更适合你的 Web 开发?
  • MySQL(三)
  • 二分类交叉熵损失
  • 在内网环境中为 Gogs 配置 HTTPS 访问
  • 常用的元素操作API
  • chromium魔改——navigator.webdriver 检测
  • 【无人机】无人机PX4飞控系统高级软件架构
  • 创新项目实训开发日志1
  • 21.数据链路层协议
  • 如何在本地部署魔搭上千问Qwen2.5-VL-32B-Instruct-AWQ模型在显卡1上面运行推理,并开启api服务
  • QT 中的元对象系统(五):QMetaObject::invokeMethod的使用和实现原理