VUE+Spring Flux實現SSE長連接

VUE代碼

        // 初始化EventSourceinitEventSource(url) {const token = getAccessToken();const eventSource = new EventSourcePolyfill(url, {headers: {'Authorization': `Bearer ${token}`,'tenant-id': getTenantId(),}});eventSource.onerror = (e) => {console.log("SSE連接錯誤", e);if (e.readyState === EventSource.CLOSED || eventSource.readyState === EventSource.CONNECTING) {console.log("SSE連接已關閉或正在重連");} else {// 當發生錯誤時,嘗試重新連接if (reconnectAttempts < maxReconnectAttempts) {console.log(`嘗試第${reconnectAttempts + 1}次重連`);reconnectAttempts++;setTimeout(() => {eventSource.close(); // 關閉當前連接this.initEventSource(url); // 重新初始化EventSource}, reconnectDelay * reconnectAttempts);} else {console.error("達到最大重連次數,不再嘗試重連");}}};eventSource.addEventListener("message", res => {const data = JSON.parse(res.data)if (data.type == 2) {this.unreadCount = data.content;}if (data.type == 1) {this.createNotify(data)}})},

后端采用redis做管道,能夠兼容分布式服務

JAVA 監聽接口

 @GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> streamEvents() {Long loginUserId = SecurityFrameworkUtils.getLoginUserId();USER_IDS.add(loginUserId);SseMessageVO heartbeat = new SseMessageVO().setType(SseNotifyTypeEnum.HEARTBEAT.getType()).setUserId(loginUserId).setContent("Heartbeat");return  reactiveRedisOperations.listenToChannel(SseService.getDestination(loginUserId)).map(data -> sendMsg(loginUserId,data.getMessage(),heartbeat)).publishOn(Schedulers.boundedElastic()).doOnSubscribe(subscription -> {// 訂閱時發送一次心跳,確認連接heartbeat(heartbeat);});}private String sendMsg(Long loginUserId,String sseMessage,SseMessageVO heartbeat){SseMessageVO sseMessageVO = JSONUtil.toBean(sseMessage, SseMessageVO.class);if (null != sseMessageVO && Objects.equals(sseMessageVO.getUserId(), loginUserId)){return JSONUtil.toJsonStr(sseMessageVO);}return JSONUtil.toJsonStr(heartbeat);}/*** 登錄時心跳*/private void heartbeat(SseMessageVO heartbeat) {ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();executorService.schedule(() -> {sseService.publishEventToChannel(heartbeat).subscribe();}, 1, TimeUnit.SECONDS);executorService.shutdown();}/*** 保活*/@PostConstructpublic void heartbeatTimer() {ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(() -> {if (CollectionUtil.isNotEmpty(USER_IDS)){for (Long userId : USER_IDS) {String message = "Heartbeat at " + LocalDateTime.now();SseMessageVO heartbeat = new SseMessageVO().setType(SseNotifyTypeEnum.HEARTBEAT.getType()).setUserId(userId).setContent(message);sseService.publishEventToChannel(heartbeat).subscribe();}}}, 0, 10, TimeUnit.SECONDS);}

JAVA 提交數據服務

@Component
public class SseService {@Resourceprivate ReactiveRedisOperations<String, String> reactiveRedisOperations;private static final String DESTINATION = "event-channel-user:";/*** 獲取指定通道* @param userId* @return*/public static String getDestination(Long userId){return DESTINATION+userId;}/*** 推送事件到通道* @param sseMessageVO* @return*/public Mono<Long> publishEventToChannel(SseMessageVO sseMessageVO) {return reactiveRedisOperations.convertAndSend(getDestination(sseMessageVO.getUserId()), JSONUtil.toJsonStr(sseMessageVO));}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43596.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43596.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43596.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 下sendmessage和postmessage的區別詳解與示例

文章目錄 1、SendMessage2、PostMessage3、兩者的區別&#xff1a; 總結 在C#中&#xff0c;SendMessage和PostMessage是兩個用于Windows編程的API&#xff0c;它們用于向窗口發送消息。這兩個方法都位于System.Windows.Forms命名空間中&#xff0c;通常用于自動化Windows應用程…

GitHub:現代軟件開發的協作平臺

引言 在現代軟件開發中&#xff0c;協作工具的選擇至關重要。GitHub作為全球最大的代碼托管平臺&#xff0c;已經成為開發者們不可或缺的工具。自2008年成立以來&#xff0c;GitHub不僅改變了代碼托管和協作的方式&#xff0c;還在開源軟件的發展中扮演了重要角色。本文將詳細…

科普文:分布式系統的架構設計模式

一、分布式架構基本概念 分布式架構是一種計算機系統設計方法&#xff0c;它將一個復雜的系統劃分為多個自治的組件或節點&#xff0c;并通過網絡進行通信和協作。每個組件或節點在功能上可以相互獨立&#xff0c;但又能夠通過消息傳遞或共享數據來實現協同工作。分布式架構主要…

值傳遞與引用傳遞:深入理解Java中的變量賦值和參數傳遞機制

在Java中&#xff0c;理解值傳遞&#xff08;值拷貝&#xff09;與引用傳遞&#xff08;地址拷貝&#xff09;之間的區別對于正確處理數據結構和對象至關重要。本文將通過示例代碼深入探討這兩種機制&#xff0c;并解釋它們如何影響程序的行為。 值傳遞&#xff08;值拷貝&…

獲取腳本執行時間

在運行一些腳本時&#xff0c;時間會過期&#xff0c;這時就需要重新更新token&#xff0c;下面做了一個demo判斷時間是否過期 import datetime import time starttimedatetime.datetime.now() # 時間進行格式化 starttimestarttime.strftime("%Y-%m-%d %H:%M:%S") …

高效利用iCloud指南

高效利用 iCloud 需要了解其各種功能和最佳實踐&#xff0c;以充分發揮其云存儲和同步能力。以下是詳細的指南&#xff1a; ### 1. 設置和管理 iCloud 存儲 **初始設置** - 確保在所有設備&#xff08;iPhone、iPad、Mac&#xff09;上使用同一 Apple ID 登錄 iCloud。 - 在設…

iPaaS丨企業應用及數據集成的重要性和挑戰

在激烈的市場競爭中&#xff0c;企業服務總線和數據總線扮演著企業神經網絡的角色&#xff0c;它們將不同的業務部門、系統以及數據緊密相連&#xff0c;保障信息流通無阻&#xff0c;實現資源的高效分配。這樣的集成不僅提高了企業的運營效率&#xff0c;還增強了企業的適應性…

虛擬機因斷電進入./#狀態解決辦法

現象&#xff1a; 解決&#xff1a;先查看錯誤日志&#xff1a;journalctl -p err -b查看自己虛擬機中標黃部分的名字 之后運行&#xff1a;xfs_repair -v -L /dev/sda #這里sda用你自己標黃的 最后重啟 reboot 即可。

使用Dockerfile和ENTRYPOINT運行Python 3腳本

在Docker中運行Python 3腳本是一種常見的部署應用程序的方式。通過使用Dockerfile&#xff0c;我們可以定義一個包含Python環境和應用程序的Docker鏡像。在Dockerfile中&#xff0c;我們可以使用ENTRYPOINT指令來指定當容器啟動時應該運行的命令。 **一、創建Dockerfile** 首先…

在Linux上運行macOS:深度解析OSX-KVM項目

在Linux上運行macOS&#xff1a;深度解析OSX-KVM項目 在現代開發和測試環境中&#xff0c;能夠在不同操作系統之間無縫切換是至關重要的。對于開發者而言&#xff0c;如何在Linux系統上運行macOS一直是一個挑戰。然而&#xff0c;OSX-KVM項目為我們提供了一種高效的解決方案&a…

R包:ggsci期刊配色

介紹 不同期刊配色大多數時候不一樣&#xff0c;為了更好符合期刊圖片顏色的配色&#xff0c;有人開發了ggsci這個R包。它提供以下函數&#xff1a; scale_color_palname() scale_fill_palname() 對應不同期刊的color和fill函數。 導入數據R包 library("ggsci")…

如何一起解壓縮多個小壓縮包unzip multiprt zip file

這個問題有兩種解讀&#xff0c;一種是需要解壓這個文件夾里面的所有zip文件。另一個是壓縮文件時候存成了多個part&#xff0c;需要一起解壓縮。 環境 Ubuntu22.04 解決方法 解壓當前文件夾所有zip文件 unzip your/folder/*.zip解壓同一壓縮文件的多個part sudo apt ins…

SpringBoot使用@RestController處理GET和POST請求

在Spring MVC中&#xff0c;RestController注解的控制器類可以處理多種HTTP請求方法&#xff0c;包括GET和POST。這些請求方法通過特定的注解來映射&#xff0c;比如GetMapping用于GET請求&#xff0c;PostMapping用于POST請求。這些注解是RequestMapping的特定化版本&#xff…

2024年全面導入APS系統:提升工廠生產效率的策略

在快速變化的市場環境中&#xff0c;急單、插單、訂單設計變更、訂單交期變更、訂單取消、供應鏈移動等問題已經是制造業時時刻刻都在面對的問題&#xff0c;在訂單量下降的市場環境下&#xff0c;企業本身的業務工作反而越來越忙碌。在此背景下&#xff0c;當今制造業企業亟需…

JavaScript高級程序設計(第四版)--學習記錄之函數(下)

函數內部 ES5中,函數內部存在兩個特殊的對象:arguments和this。ES6新增了new.target屬性。 arguments arguments對象其實還有一個callee屬性,是一個指向arguments對象所在函數的指針。 function fb(num){ if(num<=1){ return 1; }else{ return num * fb(num-1); } }/*這個…

【pytorch24】Visdom可視化

TensorboardX pytorch有一個工具借鑒了tensorboard pip install tensorboardX 有查看變量的數值、監聽曲線等功能 如何使用 新建SummaryWriter()實例 要把監聽的數據&#xff0c;比如說要監聽dummy_s1[0]&#xff08;y 坐標&#xff09;存放到data/scalar1中&#xff0c;…

ASPICE是汽車軟件開發中的質量保證流程

復雜的汽車系統對軟件的質量和可靠性提出了極高的要求。為了確保汽車軟件的高質量和可靠性&#xff0c;ASPICE&#xff08;Automotive SPICE&#xff0c;汽車軟件過程改進和能力確定&#xff09;流程應運而生。本文將對ASPICE流程進行詳細介紹。 一、ASPICE概述 ASPICE是汽車行…

【React】React18 Hooks 之 useContext

目錄 useContext1、Provider和 useContext2、Provider 和Consumer3、Provider 嵌套4、React.createContext提供的Provider和class的contextType屬性5、讀、寫Context&#xff08;1&#xff09;父組件修改Context&#xff08;2&#xff09;子組件修改Context 好書推薦 useContex…

NPDP有什么價值?究竟值不值得去考?

NPDP其實就是產品經理國際資格認證&#xff0c;是美國產品開發管理協會發起的&#xff0c;集理論、方法和實踐一體&#xff0c;在新產品開發方面有一個很全面的知識體系。是國際公認的新產品開發專業認證&#xff0c;具有權威性。 NPDP能夠很好地幫你在做新產品的道路上少走彎…

【已解決】騰訊云安裝了redis,但是本地訪問不到,連接不上

匯總了我踩過的所有問題。 查看配置文件redis.conf 1、把bind 127.0.0.1給注釋掉&#xff08;前面加個#就是&#xff09;或者改成bind 0.0.0.0&#xff0c;因為剛下載時它是默認只讓本地訪問。&#xff08;linux查找文檔里的內容可以輸入/后面加需要匹配的內容&#xff0c;然后…