java使用websocket推送消息到页面

在这里插入图片描述

文章目录

  • 一、项目背景
  • 二、使用方式
    • 1.vue2+java+spring
      • pom.xml
      • RealtimeMonitor.vue
      • MonitorTaskExe.java
      • WSTopicEnum.java
      • WServerHelper.java
    • 2.vue3+java+springboot
      • pom.xml
      • TopologyView.vue
      • AlarmDataInquiryController.java
      • PushService.java
      • PushWebSocketHandler.java
      • WebSocketConfig.java
      • RepeaterNetStateEntity.java

一、项目背景

公司有2个项目,项目一采用vue2,项目二采用vue3,目前分别记录。

二、使用方式

1.vue2+java+spring

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>ems-common</artifactId><groupId>com.hero.lte.ems</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>ems-common-websocket</artifactId>
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>4.2.3.RELEASE</version></dependency><!-- http://mvnrepository.com/artifact/org.eclipse.jetty.websocket/websocket-server --><dependency><groupId>org.eclipse.jetty.websocket</groupId><artifactId>websocket-server</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId></dependency><dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId></dependency><dependency><groupId>com.hero.lte.ems</groupId><artifactId>other</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>

RealtimeMonitor.vue

data() {return {websocketSetting: [{ topic: '/user/#/realTimeMonitoring', clientId: 'monitoring', callback: this.websocketCallback }]}
}methods: {websocketInit() {socketInstance.init(this.websocketSetting);},websocketCallback(msg) {const data = JSON.parse(msg.body);const CPUUtilization = data.CPUUsage;this.$refs.realtimeCpuMonitor.getMonitorData(CPUUtilization);const memoryTotal = data.memoryTotal;const memoryUsage = data.memoryUsage;const memoryUsageRatio = data.memoryUsageRatio;this.$refs.realtimeMemoryMonitor.getMonitorData(memoryTotal, memoryUsage, memoryUsageRatio);const diskTotal = data.diskTotal;const diskUsage = data.diskUsage;const diskUtilization = data.diskUsageRatio;this.$refs.realtimeDiskMonitor.getMonitorData(diskTotal, diskUsage, diskUtilization);},mounted() {this.websocketInit();},beforeDestroy() {for (let i = 0; i < this.websocketSetting.length; i++) {socketInstance.stopReceiveTopicMsg(this.websocketSetting[i].clientId, this.websocketSetting[i].topic);}
}

MonitorTaskExe.java

import com.hero.lte.ems.websocket.server.WServerHelper;@Resource
WServerHelper serverHelper;private void realTimeMonitoring() {serverHelper.push2OneClient(WSTopicEnum.realTimeMonitoring.name(),"monitoring",JSONObject.toJSONString(jsonObj));
}

WSTopicEnum.java

package com.hero.lte.ems.websocket.enums;public enum WSTopicEnum {ElementServer,OamTaskServer,TrackReportServer,TrackTaskServer,ObserveReportServer,ObserveTaskServer,SpectrumServer,TSTaskServer,CurrentEventServer,AlarmCountServer,PmTaskServer,MsgDispathServer,AutoAlarmServer,PmCurrenttimeWsServer,NodeEventPushServer,CurrentAlarmServer,RackBoardStatusServer,MMLServer,VmQueryWsServer,VmUpdateWsServer,PocVersionServer,DHCPServer,VmQueryVersionServer,ConfigExportServer,ConsistencyServer,ConfigImportMMLServer,realTimeMonitoring,monitorServiceProcess,configBackup,ExecuteTheTaskImmediately,BatchInitNECfgServer,uploadConfigServer;public static WSTopicEnum formatEnum(String value){for(WSTopicEnum status : WSTopicEnum.values()){if(status.name().equalsIgnoreCase(value)){return status;}}return null;}
}

WServerHelper.java

package com.hero.lte.ems.websocket.server;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;@Component
public class WServerHelper {@AutowiredSimpMessagingTemplate messagingTemplate;public void push2OneClient(String topic,String channlId ,Object msg) {this.messagingTemplate.convertAndSend("/user/"+channlId+"/"+topic, msg);}public void push2AllClient(String topic,Object msg) {this.messagingTemplate.convertAndSend("/topic/"+topic, msg);}}

2.vue3+java+springboot

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>data-service-solution</artifactId><groupId>com.xnms</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>xnms-data-service</artifactId><version>1.0.0</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>com.xnms</groupId><artifactId>xnms-data-contract</artifactId><version>${project.version}</version></dependency><dependency><groupId>com.xnms</groupId><artifactId>xnms-data-service-api</artifactId><version>${project.version}</version></dependency><!-- Fastjson dependency --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.30</version> <!-- 使用最新版本的fastjson --></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Spring Boot WebSocket 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.7</version></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><!-- Apache POI for Excel --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency><dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><version>5.1.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.60.Final</version></dependency></dependencies></project>

TopologyView.vue

let webSocket = null;const connectWebSocket = (url) => {if (webSocket &&(webSocket.readyState === WebSocket.OPEN ||webSocket.readyState === WebSocket.CONNECTING)) {return;}webSocket = new WebSocket(url);webSocket.onopen = () => console.log("TopologyView.vue WebSocket已连接");webSocket.onmessage = handleWebSocketMessage;webSocket.onclose = () => console.log("TopologyView.vue WebSocket已关闭");webSocket.onerror = (error) =>console.error("TopologyView.vue WebSocket错误:", error);
};// WebSocket处理逻辑
const handleWebSocketMessage = (event) => {try {const message = JSON.parse(event.data);......} catch (error) {console.error("TopologyView.vue WebSocket消息处理错误:", error);}
};onUnmounted(() => {if (webSocket &&(webSocket.readyState === WebSocket.OPEN ||webSocket.readyState === WebSocket.CONNECTING)) {webSocket.close();}
});onMounted(async () => {connectWebSocket("/ws/topoView");
}

AlarmDataInquiryController.java

@Operation(summary = "根据站点ID集合查询站点详细信息")
@GetMapping(value = "/testWebsocketRepeaterNetState")
public ResponseModel<List<Repeater>> testWebsocketRepeaterNetState(@RequestParam String repeaterId, @RequestParam Integer rptState, @RequestParam String serialNo){RepeaterNetStateEntity repeaterNetStateEntity = new RepeaterNetStateEntity();repeaterNetStateEntity.setRepeaterId(repeaterId);repeaterNetStateEntity.setRptState(rptState);repeaterNetStateEntity.setSerialNo(serialNo);pushService.messageDataFormatting("topoView", repeaterNetStateEntity);return ResponseModel.ofSuccess();
}

PushService.java

package com.xnms.data.service.service.impl.websocket;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;@Service
public class PushService {/*** 🌟 向指定频道推送消息* @param channel 频道名称(对应URL路径)* @param message 消息内容*/public void pushToChannel(String channel, String message) {CopyOnWriteArraySet<WebSocketSession> sessions = PushWebSocketHandler.channelSessions.get(channel);if (sessions != null) {sessions.forEach(session -> {try {if (session.isOpen()) {session.sendMessage(new TextMessage(message));}} catch (IOException e) {// 处理异常}});}}/*** 🌟 广播所有频道* @param message 消息内容*/public void broadcast(String message) {PushWebSocketHandler.channelSessions.values().forEach(sessions -> {sessions.forEach(session -> {try {if (session.isOpen()) {session.sendMessage(new TextMessage(message));}} catch (IOException e) {// 处理异常}});});}/*** 数据格式化*/public void messageDataFormatting(String path, Object data){ObjectMapper objectMapper = new ObjectMapper();String message = null;try {message = objectMapper.writeValueAsString(data);} catch (JsonProcessingException e) {throw new RuntimeException(e);}this.pushToChannel(path, message);}}

PushWebSocketHandler.java

package com.xnms.data.service.service.impl.websocket;import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;public class PushWebSocketHandler extends TextWebSocketHandler {// 🌟 多频道存储结构:channel -> sessionsstatic final ConcurrentMap<String, CopyOnWriteArraySet<WebSocketSession>> channelSessions =new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {String channel = getChannelFromSession(session);channelSessions.computeIfAbsent(channel, k -> new CopyOnWriteArraySet<>()).add(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {String channel = getChannelFromSession(session);CopyOnWriteArraySet<WebSocketSession> sessions = channelSessions.get(channel);if (sessions != null) {sessions.remove(session);if (sessions.isEmpty()) {channelSessions.remove(channel);}}}private String getChannelFromSession(WebSocketSession session) {return (String) session.getAttributes().get("channel");}
}

WebSocketConfig.java

package com.xnms.data.service.service.impl.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import java.util.Map;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(pushWebSocketHandler(), "/{channel}").addInterceptors(new ChannelInterceptor()).setAllowedOrigins("*");}@Beanpublic WebSocketHandler pushWebSocketHandler() {return new PushWebSocketHandler();}/*** 🌟 频道拦截器(用于获取路径参数)*/private static class ChannelInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Map<String, Object> attributes) {String channel = ((ServletServerHttpRequest) request).getServletRequest().getRequestURI().split("/")[1];attributes.put("channel", channel);try {return super.beforeHandshake(request, response, wsHandler, attributes);} catch (Exception e) {throw new RuntimeException(e);}}}
}

RepeaterNetStateEntity.java

package com.xnms.data.service.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class RepeaterNetStateEntity {private String repeaterId;private int rptState;private String serialNo;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/78702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小市值策略复现(A股选股框架回测系统)

相关config配置 https://quantkt.com/forumDetail?id201043 很早就知道了小市值模型&#xff0c;正好量化选股回测框架出来了&#xff0c;把最裸的小市值复现下&#xff0c;顺便验证下框架逻辑。 科普: 小市值策略基于 “小市值效应”&#xff0c;即从历史数据来看&#xf…

解决 Flutter 在 iOS 真机上构建失败的问题

在开发 Flutter 应用时&#xff0c;有时会在尝试将应用部署到 iOS 真机时遇到构建失败的问题。错误信息通常类似于以下内容&#xff1a; Could not build the precompiled application for the device. Uncategorized (Xcode): Timed out waiting for all destinations matchi…

OCR(Optical Character Recognition),光学字符识别

参考&#xff1a;如何让机器读懂图片上的文字&#xff1f;飞桨助您快速了解OCR - 知乎 OCR&#xff08;Optical Character Recognition&#xff09;&#xff0c;译为光学字符识别&#xff0c;是指通过扫描等光学输入方式将各种票据、报刊、书籍、文稿及其它印刷品的文字转化为图…

一网统管建设组织保障分工常见表

在 “一网统管” 建设进程中,强有力的组织保障体系与各业务部门间的紧密分工协作是确保建设成效的关键。 从组织保障层面来看,需建立专门的 “一网统管” 建设领导小组,由政府高层领导担任组长,各关键业务部门负责人作为组员,以此强化对整体建设工作的统筹规划与组…

Python中的defaultdict方法

文章目录 核心特点基本语法常见使用场景1. 分组数据&#xff08;默认值为列表&#xff09;2. 计数&#xff08;默认值为整数&#xff09;3. 集合操作&#xff08;默认值为集合&#xff09;4. 嵌套字典 注意事项与普通字典对比总结1. 键&#xff08;Key&#xff09;的类型2. 值&…

结构化数据、半结构化数据、非结构化数据 差异与实践指南

结构化数据、半结构化数据、非结构化数据 差异与实践指南 一、核心概念与差异对比 维度结构化数据半结构化数据非结构化数据数据结构固定Schema&#xff08;行列明确&#xff09;含标签/层级结构&#xff08;无固定Schema&#xff09;无预定义结构存储方式关系型数据库&#x…

【AI News | 20250429】每日AI进展

AI Repos 1、aci ACI.dev是一个开源基础设施层&#xff0c;旨在为AI智能体的工具使用提供支持。它通过统一的模型-上下文-协议&#xff08;MCP&#xff09;服务器或轻量级Python SDK&#xff0c;使智能体能够以感知意图的方式访问600多种工具&#xff0c;并具备多租户认证、细…

【C++ 类和数据抽象】消息处理示例(1):从设计模式到实战应用

目录 一、数据抽象概述 二、消息处理的核心概念 2.1 什么是消息处理&#xff1f; 2.2 消息处理的核心目标 三、基于设计模式的消息处理实现 3.1 观察者模式&#xff08;Observer Pattern&#xff09; 3.2 命令模式&#xff08;Command Pattern&#xff09; 四、实战场景…

【Android】自定义Trace

1&#xff0c;Trace分析 Android掉帧分析-CSDN博客 2&#xff0c;自定义Trace 以下&#xff0c;android.os.Trace公开了以下API 1&#xff0c;beginSection与endSection联合使用&#xff0c;只能在同一个线程 2&#xff0c;beginAsyncSection与endAsyncSection可以在不同线程…

基于tabula对pdf中的excel进行识别并转换成word(三)

上一节中是基于PaddleOCR对图片中的excel进行识别并转换成word优化&#xff0c;本节改变思路&#xff0c;直接从pdf中读取表格的信息&#xff0c;具体思路如下所述。 PDF中的表格数据如下截图所示&#xff1a; 一、基于tabula从PDF中提取表格 df_list tabula.read_pdf("…

Java中的接口和抽象类

Java 抽象类与接口&#xff1a;区别、应用与选择 在 Java 编程的世界里&#xff0c;抽象类和接口是两个极为重要的概念&#xff0c;它们在实现代码抽象、提高代码复用性和可维护性方面发挥着关键作用。然而&#xff0c;很多开发者在使用时容易混淆这两个概念。本文将深入探讨 …

Java读Excel:解析阿里云easyExcel导入文件的行号

文章目录 引言I 解析阿里云easyExcel导入文件的行号声明解析对象的基类判断Excel解析对象类型是否包含继承某个类 isAssignableFromJava 转换list类型并设置下标到元素对象属性II 封装excel 文件读取excel 文件读取用法文件导入上下文III 参数校验工具类校验参数是否合法 (jaka…

mmap核心原理和用途及其与内存映射段的关系

mmap 是 Linux/Unix 系统中的一个关键系统调用&#xff0c;全称是 Memory Map&#xff08;内存映射&#xff09;。它的核心功能是将 文件、设备或匿名内存 直接映射到进程的虚拟地址空间&#xff0c;从而实现高效的内存访问和操作。以下是其核心原理和用途的详细说明&#xff1…

数据库概论速成期中版

文章目录 引论数据库用户Casual usersNaive usersApplication programmersDatabase administrators 关系模型CAP数据库两种描述关系数据库的方式简单总结 第一范式规则第二范式规则举个例子符合第二规则的操作不符合第二规则的操作 第三范式规则key,superkey,null values,主键&…

解决调用Claude 3.7接口 403 Request not allowed问题

1. 遇到问题 Python 基于 Langchain 对接 Claude 3.7 大模型接口进行问答时&#xff0c;由于国内不在Claude支持的国家和地区&#xff0c;所以一直调不通&#xff0c;错误 anthropic.PermissionDeniedError: Error code: 403 - {error: {type: forbidden, message: Request…

Vue2+Vue3学习笔记

Vue基础介绍 下载并安装vue.js v2 https://v2.cn.vuejs.org/https://v2.cn.vuejs.org/ v3 https://v3.cn.vuejs.org/ 会重定向到Vue.js - 渐进式 JavaScript 框架 | Vue.jsVue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/ 从v2过渡到v3 在F盘创建v2v3学习笔记 并…

2025年KBS新算法 SCI1区TOP:长颖燕麦优化算法AOO,深度解析+性能实测

目录 1.摘要2.算法原理3.结果展示4.参考文献5.文章&代码获取 1.摘要 本文提出了一种新颖的元启发式算法——长颖燕麦优化算法&#xff08;AOO&#xff09;&#xff0c;该算法灵感来自动画燕麦在环境中的自然行为。AOO模拟了长颖燕麦的三种独特行为&#xff1a;(i) 通过自然…

CentosLinux系统crontab发现执行删除命令失效解决方法

权限或安全策略限制 ​​可能场景​​&#xff1a; ​​### ​​目录权限冲突​​&#xff1a; 你的目录权限为 drwxr-xr-x&#xff08;属主 mssql&#xff09;&#xff0c;但 cron 任务以 root 执行。 ​​风险点​​&#xff1a;若目录内文件属主为 mssql 且权限为 700&…

后验概率最大化(MAP)估计算法原理以及相具体的应用实例附C++代码示例

1. MAP估计基本原理 MAP&#xff08;Maximum A Posteriori&#xff0c;最大后验概率估计&#xff09;是贝叶斯推断中的重要概念&#xff0c;它的目标是&#xff1a; 给定观测数据&#xff0c;找到使得后验概率最大的参数值。 公式化表示&#xff1a; [ θ MAP arg ⁡ max ⁡…

16、路由守卫:设置魔法结界——React 19 React Router

一、魔法结界的本质 "路由守卫是霍格沃茨城堡的隐身斗篷&#xff0c;在时空裂隙中精准控制维度跃迁&#xff01;" 魔法部交通司官员挥舞魔杖&#xff0c;React Router 的嵌套路由在空中交织成星轨矩阵。 ——基于《国际魔法联合会》第7号时空协议&#xff0c;路由守…