最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Spring SseEmitter實現(xiàn)服務端推送的示例代碼

 更新時間:2026年02月28日 08:41:17   作者:gs80140  
SseEmitter 是 Spring MVC 4.2+ 引入的一個類,專門用于實現(xiàn) Server-Sent Events (SSE),相比于 WebSocket,SSE 更輕量(基于 HTTP 協(xié)議),且支持自動重連,所以本文給大家介紹了如何使用Spring SseEmitter實現(xiàn)服務端推送,需要的朋友可以參考下

SseEmitter 是 Spring MVC 4.2+ 引入的一個類,專門用于實現(xiàn) Server-Sent Events (SSE)。簡單來說,SSE 允許服務器在建立連接后,主動向客戶端推送數(shù)據(jù),而不需要客戶端反復輪詢。

相比于 WebSocket,SSE 更輕量(基于 HTTP 協(xié)議),且支持自動重連。它非常適合像實時通知、股價更新、大模型(LLM)流式輸出這類單向推送場景。

核心原理解析

在傳統(tǒng)的 HTTP 請求中,客戶端發(fā)送請求,服務器返回響應,然后連接關閉。而 SseEmitter 改變了這種模式:

  1. 保持連接:服務器返回的響應頭包含 Content-Type: text/event-stream
  2. 分塊傳輸:連接保持打開狀態(tài),服務器可以多次調(diào)用 emitter.send() 發(fā)送數(shù)據(jù)包。
  3. 結束生命周期:手動調(diào)用 complete() 或因為超時/錯誤觸發(fā) onTimeout/onError。

前言

在實時性需求日益增長的今天,我們不一定非要動用“重型武器” WebSocket。如果你只需要服務器向客戶端推送消息(如:進度條更新、ChatCompletion 響應),Spring 提供的 SseEmitter 可能是你的最佳選擇。

一、 核心代碼實現(xiàn)

使用 SseEmitter 通常分為三步:創(chuàng)建連接、保存引用、推送消息。

1. 控制器層 (Controller)

這是建立連接的入口。

@RestController
@RequestMapping("/api/sse")
public class SseController {

    // 用于存儲已連接的客戶端,實際生產(chǎn)中建議使用專門的服務類管理
    private static final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    @GetMapping(value = "/subscribe/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe(@PathVariable String userId) {
        // 設置超時時間(單位毫秒),0 表示永不超時
        SseEmitter emitter = new SseEmitter(60_000L); 

        emitters.put(userId, emitter);

        // 注冊回調(diào)
        emitter.onCompletion(() -> emitters.remove(userId));
        emitter.onTimeout(() -> emitters.remove(userId));
        emitter.onError((e) -> emitters.remove(userId));

        // 建立連接后立即發(fā)送一條消息,防止某些代理或瀏覽器認為連接已失效
        try {
            emitter.send(SseEmitter.event().name("INIT").data("Connected!"));
        } catch (IOException e) {
            emitter.completeWithError(e);
        }

        return emitter;
    }
}

2. 消息推送邏輯

你可以從任何異步線程調(diào)用 send 方法。

public void sendMessage(String userId, String content) {
    SseEmitter emitter = emitters.get(userId);
    if (emitter != null) {
        try {
            // 可以發(fā)送純文本,也可以發(fā)送封裝好的對象(會自動轉(zhuǎn) JSON)
            emitter.send(SseEmitter.event()
                    .id(UUID.randomUUID().toString())
                    .name("message") // 對應前端的事件名
                    .data(content)
                    .reconnectTime(3000)); // 提示客戶端重連間隔
        } catch (IOException e) {
            emitters.remove(userId);
            emitter.completeWithError(e);
        }
    }
}

二、 前端如何接收?

瀏覽器內(nèi)置了 EventSource API,調(diào)用非常簡單:

const eventSource = new EventSource('/api/sse/subscribe/user123');

eventSource.onmessage = (event) => {
    console.log("收到通用消息:", event.data);
};

// 監(jiān)聽特定類型的事件 (對應后端的 .name("message"))
eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log("處理后的數(shù)據(jù):", data);
});

eventSource.onerror = (error) => {
    console.error("SSE 錯誤:", error);
    eventSource.close();
};

三、 避坑指南(關鍵技巧)

  1. Nginx 配置:如果你使用了 Nginx 代理,必須配置 proxy_buffering off;proxy_set_header Connection "";,否則 Nginx 會緩存消息直到緩沖區(qū)滿才一次性發(fā)給前端。
  2. 容器線程限制:雖然 SseEmitter 是異步的,但它依然占用一個 HTTP 連接。在高并發(fā)場景下,需要調(diào)整 Web 容器(如 Tomcat)的最大連接數(shù)。
  3. 超時處理:瀏覽器默認會在 SSE 斷開后自動重連。在 onTimeout 中,務必調(diào)用 emitter.complete() 來清理服務器資源。
  4. 跨域問題:確保 CORS 配置允許 Last-Event-ID 等特殊請求頭。

總結

SseEmitter 是 Spring 為我們封裝的一把“輕巧的瑞士軍刀”。它規(guī)避了 WebSocket 復雜的握手和協(xié)議轉(zhuǎn)換,在處理流式輸出(如 AI 對話響應)時表現(xiàn)極佳。

以上就是使用Spring SseEmitter實現(xiàn)服務端推送的示例代碼的詳細內(nèi)容,更多關于Spring SseEmitter服務端推送的資料請關注腳本之家其它相關文章!

相關文章

  • IntelliJ?IDEA社區(qū)版2021.3配置SpringBoot項目詳細教程及失敗案例

    IntelliJ?IDEA社區(qū)版2021.3配置SpringBoot項目詳細教程及失敗案例

    IntelliJ?IDEA?2021.3.3是一款集成開發(fā)環(huán)境,用于Java和其他編程語言的開發(fā),下面這篇文章主要給大家介紹了關于IntelliJ?IDEA社區(qū)版2021.3配置SpringBoot項目詳細教程及失敗案例的相關資料,需要的朋友可以參考下
    2024-03-03
  • idea本地jar使用maven打包本地依賴實現(xiàn)自動編譯到項目里的操作

    idea本地jar使用maven打包本地依賴實現(xiàn)自動編譯到項目里的操作

    這篇文章主要介紹了idea本地jar使用maven打包本地依賴實現(xiàn)自動編譯到項目里的操作,本文通過示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Java連接SQL?Server數(shù)據(jù)庫的超詳細教程

    Java連接SQL?Server數(shù)據(jù)庫的超詳細教程

    在Java應用程序中我們經(jīng)常需要與數(shù)據(jù)庫進行交互,一種常見的數(shù)據(jù)庫是Microsoft?SQL?Server,下面這篇文章主要給大家介紹了關于Java連接SQL?Server數(shù)據(jù)庫的超詳細教程,需要的朋友可以參考下
    2024-01-01
  • Java中equals和hashcode用法

    Java中equals和hashcode用法

    `equals`和`hashCode`方法在Java中密切相關,必須保持一致性,如果兩個對象通過`equals`方法相等,它們的`hashCode`也必須相同,這對于基于哈希的數(shù)據(jù)結構至關重要,因為這些結構依賴哈希值進行快速查找和存儲,為了減少哈希沖突
    2025-01-01
  • SpringBoot中的手動提交事務

    SpringBoot中的手動提交事務

    在Spring框架中使用@Transactional注解通常管理事務,但在多線程環(huán)境下此方法失效,本文討論了手動事務的必要性及其實現(xiàn)方式,探討了Spring的七種事務傳播行為和數(shù)據(jù)庫的四大特性與隔離級別,了解這些可以幫助開發(fā)者在無法使用聲明式事務時
    2024-09-09
  • @Valid和@Validated注解校驗以及異常處理方式

    @Valid和@Validated注解校驗以及異常處理方式

    在Javaweb開發(fā)中,防止數(shù)據(jù)庫惡意攻擊是至關重要的,盡管前端校驗可以起到一定的篩選作用,但通過工具如postman直接對后端發(fā)起請求的情況仍然需要后端進行嚴格的數(shù)據(jù)校驗,Java生態(tài)下,@Valid注解配合SpringBoot提供了一個便捷高效的后端數(shù)據(jù)校驗方案
    2024-11-11
  • Java中的synchronized有幾種加鎖方式(實例詳解)

    Java中的synchronized有幾種加鎖方式(實例詳解)

    在Java中,synchronized關鍵字提供了內(nèi)置的支持來實現(xiàn)同步訪問共享資源,以避免并發(fā)問題,這篇文章主要介紹了java的synchronized有幾種加鎖方式,需要的朋友可以參考下
    2024-05-05
  • IDEA 2020.1.1好用的plugins插件推薦

    IDEA 2020.1.1好用的plugins插件推薦

    這篇文章主要介紹了IDEA 2020.1.1好用的plugins插件推薦,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Java中的byte & 0xff到底有什么作用?

    Java中的byte & 0xff到底有什么作用?

    這篇文章主要介紹了Java中的byte & 0xff到底有什么作用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Freemarker常用指令使用示例

    Freemarker常用指令使用示例

    這篇文章主要介紹了Freemarker常用指令使用示例,步驟簡單,大家參考使用吧
    2013-11-11

最新評論

米林县| 江源县| 永城市| 临清市| 都安| 黑水县| 邢台县| 平昌县| 奎屯市| 长海县| 哈巴河县| 巴彦淖尔市| 临清市| 梅河口市| 诸城市| 肥乡县| 武鸣县| 恩平市| 蓝山县| 南丰县| 镇江市| 承德市| 那曲县| 团风县| 启东市| 蒙山县| 郓城县| 普兰店市| 岐山县| 武平县| 漠河县| 凤凰县| 南江县| 克拉玛依市| 济阳县| 阿拉善右旗| 鱼台县| 兴化市| 兰溪市| 广昌县| 淄博市|