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.pswp.cn/pingmian/78702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78702.shtml
英文地址,請注明出處:http://en.pswp.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;路由守…