Spring中實(shí)現(xiàn)的三種異步流式接口方法
前言
在現(xiàn)代Web開(kāi)發(fā)中,接口超時(shí)是一個(gè)常見(jiàn)的問(wèn)題,尤其是在處理耗時(shí)操作時(shí)。傳統(tǒng)的同步接口在處理長(zhǎng)時(shí)間任務(wù)時(shí)會(huì)阻塞請(qǐng)求線程,從而影響系統(tǒng)的響應(yīng)能力。Spring框架提供了多種工具來(lái)支持異步流式接口,從而有效地解決這一問(wèn)題。本文將詳細(xì)講解Spring中實(shí)現(xiàn)的三種異步流式接口方法:ResponseBodyEmitter、SseEmitter和StreamingResponseBody。
一、ResponseBodyEmitter
ResponseBodyEmitter適用于需要?jiǎng)討B(tài)生成內(nèi)容并逐步發(fā)送給客戶端的場(chǎng)景,例如文件上傳進(jìn)度、實(shí)時(shí)日志等。使用ResponseBodyEmitter,可以在任務(wù)執(zhí)行過(guò)程中逐步向客戶端發(fā)送更新,使交互體驗(yàn)更加生動(dòng)和自然。
使用示例:
@GetMapping("/bodyEmitter") public ResponseBodyEmitter handle() { // 創(chuàng)建一個(gè)ResponseBodyEmitter,-1代表不超時(shí) ResponseBodyEmitter emitter = new ResponseBodyEmitter(-1L); // 異步執(zhí)行耗時(shí)操作 CompletableFuture.runAsync(() -> { try { for (int i = 0; i < 10000; i++) { System.out.println("bodyEmitter " + i); // 發(fā)送數(shù)據(jù) emitter.send("bodyEmitter " + i + " @ " + new Date() + "\n"); Thread.sleep(2000); } // 完成 emitter.complete(); } catch (Exception e) { // 發(fā)生異常時(shí)結(jié)束接口 emitter.completeWithError(e); } }); return emitter; }
在這個(gè)示例中,通過(guò)模擬每2秒響應(yīng)一次結(jié)果,可以看到頁(yè)面數(shù)據(jù)在動(dòng)態(tài)生成。ResponseBodyEmitter的超時(shí)時(shí)間可以設(shè)置為0或-1,表示連接不會(huì)超時(shí)。如果不設(shè)置,到達(dá)默認(rèn)的超時(shí)時(shí)間后連接會(huì)自動(dòng)斷開(kāi)。
二、SseEmitter
SseEmitter是ResponseBodyEmitter的一個(gè)子類,主要用于服務(wù)器向客戶端推送實(shí)時(shí)數(shù)據(jù),如實(shí)時(shí)消息推送、狀態(tài)更新等場(chǎng)景。Server-Sent Events (SSE)技術(shù)在服務(wù)器和客戶端之間打開(kāi)一個(gè)單向通道,服務(wù)端響應(yīng)的不再是一次性的數(shù)據(jù)包,而是text/event-stream類型的數(shù)據(jù)流信息。
使用示例:
@GetMapping("/subSseEmitter/{userId}") public SseEmitter sseEmitter(@PathVariable String userId) { log.info("sseEmitter: {}", userId); SseEmitter emitterTmp = new SseEmitter(-1L); // 將SseEmitter對(duì)象進(jìn)行持久化,以便在消息產(chǎn)生時(shí)直接取出對(duì)應(yīng)的發(fā)送器 EMITTER_MAP.put(userId, emitterTmp); CompletableFuture.runAsync(() -> { try { // 模擬發(fā)送數(shù)據(jù) SseEmitter.SseEventBuilder event = SseEmitter.event() .data("sseEmitter" + userId + " @ " + LocalTime.now()); emitterTmp.send(event); // 這里可以添加更多的發(fā)送邏輯 } catch (Exception e) { emitterTmp.completeWithError(e); } }); return emitterTmp; }
在客戶端,可以通過(guò)EventSource對(duì)象建立連接,并監(jiān)聽(tīng)message事件來(lái)接收服務(wù)器發(fā)送的數(shù)據(jù)。
三、StreamingResponseBody
StreamingResponseBody用于將響應(yīng)體作為流來(lái)輸出,適用于需要輸出大量數(shù)據(jù)且不適合使用ResponseBodyEmitter或SseEmitter的場(chǎng)景。
使用示例:
@GetMapping("/streaming") public StreamingResponseBody streaming() { return outputStream -> { // 異步執(zhí)行耗時(shí)操作 CompletableFuture.runAsync(() -> { try { for (int i = 0; i < 10000; i++) { String data = "Streaming data " + i + "\n"; outputStream.write(data.getBytes()); outputStream.flush(); Thread.sleep(1000); } outputStream.close(); } catch (Exception e) { // 處理異常 } }); }; }
在這個(gè)示例中,通過(guò)異步執(zhí)行耗時(shí)操作,逐步將數(shù)據(jù)寫入到響應(yīng)的輸出流中。StreamingResponseBody適用于需要持續(xù)輸出數(shù)據(jù)流的場(chǎng)景,例如視頻流、文件下載等。
總結(jié)
通過(guò)使用ResponseBodyEmitter、SseEmitter和StreamingResponseBody,Spring框架提供了強(qiáng)大的異步流式接口支持,有效地解決了接口超時(shí)的問(wèn)題。這些方法允許在任務(wù)執(zhí)行過(guò)程中逐步向客戶端發(fā)送更新,提高了系統(tǒng)的響應(yīng)能力和用戶體驗(yàn)。根據(jù)具體的應(yīng)用場(chǎng)景,可以選擇合適的工具來(lái)實(shí)現(xiàn)異步流式接口。
以上就是Spring中實(shí)現(xiàn)的三種異步流式接口方法的詳細(xì)內(nèi)容,更多關(guān)于Spring異步流式接口方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java動(dòng)態(tài)獲取實(shí)現(xiàn)某個(gè)接口下所有的實(shí)現(xiàn)類對(duì)象集合
今天小編就為大家分享一篇關(guān)于Java動(dòng)態(tài)獲取實(shí)現(xiàn)某個(gè)接口下所有的實(shí)現(xiàn)類對(duì)象集合,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12java8如何根據(jù)list對(duì)象中的屬性過(guò)濾篩選
這篇文章主要介紹了java8如何根據(jù)list對(duì)象中的屬性過(guò)濾篩選,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Spring中Service注入多個(gè)實(shí)現(xiàn)類的方法詳解
這篇文章主要介紹了Spring中Service注入多個(gè)實(shí)現(xiàn)類的方法詳解,Spring是一個(gè)開(kāi)源的Java框架,用于構(gòu)建企業(yè)級(jí)應(yīng)用程序,它提供了許多功能,如依賴注入、面向切面編程、數(shù)據(jù)訪問(wèn)、Web開(kāi)發(fā)等,需要的朋友可以參考下2023-07-07SpringBoot整合screw實(shí)現(xiàn)自動(dòng)生成數(shù)據(jù)庫(kù)設(shè)計(jì)文檔
使用navicat工作的話,導(dǎo)出的格式是excel不符合格式,還得自己整理。所以本文將用screw工具包,整合到springboot的項(xiàng)目中便可以自動(dòng)生成數(shù)據(jù)庫(kù)設(shè)計(jì)文檔,非常方便,下面就分享一下教程2022-11-11Spring Boot Async異步執(zhí)行任務(wù)過(guò)程詳解
這篇文章主要介紹了Spring Boot Async異步執(zhí)行任務(wù)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08利用Sharding-Jdbc組件實(shí)現(xiàn)分表
這篇文章主要為大家詳細(xì)介紹了利用Sharding-Jdbc組件實(shí)現(xiàn)分表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07詳解Spring系列之@ComponentScan批量注冊(cè)bean
本文介紹各種@ComponentScan批量掃描注冊(cè)bean的基本使用以及進(jìn)階用法和@Componet及其衍生注解使用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-02-02Spring Boot 結(jié)合 aop 實(shí)現(xiàn)讀寫分離
這篇文章主要介紹了Spring Boot 結(jié)合 aop 實(shí)現(xiàn)讀寫分離的示例,幫助大家更好的理解和使用Spring Boot框架,感興趣的朋友可以了解下2020-11-11Java編程實(shí)現(xiàn)beta分布的采樣或抽樣實(shí)例代碼
這篇文章主要介紹了Java編程實(shí)現(xiàn)beta分布的采樣或抽樣實(shí)例,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Java JDBC API介紹與實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池流程
JDBC是指Java數(shù)據(jù)庫(kù)連接,是一種標(biāo)準(zhǔn)Java應(yīng)用編程接口( JAVA API),用來(lái)連接 Java 編程語(yǔ)言和廣泛的數(shù)據(jù)庫(kù)。從根本上來(lái)說(shuō),JDBC 是一種規(guī)范,它提供了一套完整的接口,允許便攜式訪問(wèn)到底層數(shù)據(jù)庫(kù),本篇文章我們來(lái)了解JDBC API及數(shù)據(jù)庫(kù)連接池2022-12-12