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

Spring Boot中使用SSE(Server-Sent Events)實現(xiàn)聊天功能:替代websocket服務器推送

 更新時間:2026年03月14日 08:54:08   作者:weixin_39659837  
本文講解了如何在Spring Boot項目中使用SSE實現(xiàn)聊天功能,SSE適用于客戶端只需要接收更新的應用場景,而WebSocket則適合全雙工通信,客戶端通過服務端的/subscribe接口維持長連接,服務端通過SseEmitter對象發(fā)送消息

一、概述

提到服務端數(shù)據(jù)推送,你可以一下子就想到了Websocket,WebSocket是一種全新的協(xié)議,隨著HTML5草案的不斷完善,越來越多的現(xiàn)代瀏覽器開始全面支持WebSocket技術了,它將TCP的Socket(套接字)應用在了webpage上,從而使通信雙方建立起一個保持在活動狀態(tài)連接通道。

但你可能不知道,HTML5中有一個輕量的替代Websocket的方案:SSE(Server-Sent Events)。

WebSocket 和 SSE 都是傳統(tǒng)請求-響應 Web 架構的替代方案,但它們不是完全沖突的技術。 - WebSocket 架構在客戶端與服務器之間打開一個套接字,用于實現(xiàn)全雙工(雙向)通信。 無需發(fā)送 GET 消息并等待服務器響應,客戶端只需監(jiān)聽該套接字,接收服務器更新,并使用收到的數(shù)據(jù)來發(fā)起或支持各種交互。 客戶端也可以使用套接字與服務器通信,例如在成功收到更新時發(fā)送 ACK 消息。 - SSE 是一種更簡單的標準,是作為 HTML5 的擴展而開發(fā)的。 盡管 SSE 支持從服務器向客戶端發(fā)送異步消息,但客戶端無法向服務器發(fā)送消息。 對于客戶端只需接收從服務器傳入的更新的應用程序,SSE 的半雙工通信模型最適合。 與 WebSocket 相比,SSE 的一個優(yōu)勢是它是基于 HTTP 而運行的,不需要其他組件。

幾乎所有現(xiàn)代瀏覽器都支持 WebSocket 協(xié)議,包括移動瀏覽器。然而Microsoft IE 和 Edge不支持SSE 但這并不妨礙我們使用SSE,畢竟用IE的人還有幾個呢?如果是內(nèi)部使用,為什么不使用更簡單的SSE呢?

這里講述如何使用SSE建立服務端的推送。

二、服務端

這里我們使用聊天來模擬SSE的數(shù)據(jù)推送。我這里寫了幾個自定義的對象 - Chater對象存儲聊天人的信息。 - WebSSEUser是一個存儲用戶名userName和Chater對象的map。

2.1 配置

在Springboot項目中使用SSE,是不需要額外引入依賴的,只需要把spring-boot-starter-web引入即可。也不需要額外的配置。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.2 服務端text/event-stream長連接

要使用SSE,首先需要定義一個維持SSE長連接的接口地址,就像websocket中定義websocket的端口地址一樣,但是SSE這里和普通的http沒有多大區(qū)別,只是響應頭是text/event-stream.

示例:

@GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter to(HttpServletRequest request) {
    String userName = (String) request.getSession().getAttribute("userName");
    // 超時時間設置為3分鐘
    SseEmitter sseEmitter = new SseEmitter(180000L);
    Chater chater = WebSSEUser.getChater(userName);
    sseEmitter.onTimeout(() -> chater.setSseEmitter(null));
    sseEmitter.onCompletion(() -> System.out.println("完成?。?!"));
    chater.setSseEmitter(sseEmitter);
    return sseEmitter;
}

這里是Springboot應用中使用SSE,我定義了/subscribe接口: - produces指定了響應類型text/event-stream - userName從session中獲取,并獲取到聊天對象Chater。 - 這里調(diào)用時創(chuàng)建SseEmitter對象,設置超時時間3分鐘,onTimeout超時后清除SseEmitter對象,因為SSE可以超時重連,超時會再次調(diào)用這個接口,就會重新生成SseEmitter對象。 - onCompletion完成后邏輯自定義,但是不要清除SseEmitter對象,否則會一直重連。

SSE調(diào)用/subscribe接口接口以后,會一直使用一個請求,類似websocket。

2.3 服務端發(fā)送消息

上面的代碼只是保持了長連接,而且是單向的,只能是服務端給客戶端發(fā)消息。

單向的意思就是,客戶端不能通過SSE去發(fā)送消息,服務端可以通過SSE給客戶端發(fā)送消息。

但是我們還是可以使用SSE來完成聊天功能的,因為客戶端可以通過普通http請求去發(fā)送消息,到服務端以后再發(fā)送給其他客戶端。

示例:

@RequestMapping(value = "/send")
public ResultModel send(@RequestBody MessageDTO<String> messageDTO, HttpServletRequest request) {
    logger.info("收到發(fā)往用戶[{}]的文本請求;", messageDTO.getTargetUserName());
    Object userName = request.getSession().getAttribute("userName");
    if (userName == null)
        return ResultModel.error("無用戶");
    messageDTO.setFromUserName((String) userName);
    messageDTO.setMessageType(Type.TYPE_TEXT.getMessageType());
    Chater chater = WebSSEUser.getChater(messageDTO.getTargetUserName());
    try {
        chater.getSseEmitter().send(messageDTO);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return ResultModel.ok();
}

這里,通過目標的userName獲取到Chater對象,然后Chater對象中保存有SseEmitter對象,SseEmitter對象可以直接發(fā)送消息到客戶端。

三、客戶端

前面講述了服務端維持SSE的方法。下面講述下客戶端如何操作。

3.1 SSE連接

調(diào)用服務端的/subscribe接口,維持長連接,請閱服務端消息。

var url = "/subscribe";
var es = new EventSource(url);
es.addEventListener("message", function(e){
    decode(e);
},false);

不需要額外引入js,addEventListener中可以調(diào)用其他方法對消息解析并操作。

這里的decode(e);是對應服務端的chater.getSseEmitter().send(messageDTO);

3.2 普通http請求發(fā)送消息

普通的ajax請求即可,無需額外處理,調(diào)用服務端的/send接口即可。

四、控制臺截圖

如圖:

SSE(Server-Sent Events)實現(xiàn)聊天功能控制臺截圖
  1. 客戶端連接服務端的/subscribe接口,這個連接會一直持續(xù)下去,圖上已經(jīng)持續(xù)了十幾秒。
  2. 客戶端連接服務端的/send接口,發(fā)送消息給服務端,服務端轉(zhuǎn)發(fā)給其他客戶端。

到此這篇關于Spring Boot中使用SSE(Server-Sent Events)實現(xiàn)聊天功能:替代websocket服務器推送的文章就介紹到這了,更多相關SSE(Server-Sent Events)替代websocket內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Mybatis-Plus的條件構造器QueryWrapper & UpdateWrapper示例詳解

    Mybatis-Plus的條件構造器QueryWrapper & UpdateWrapper示例詳解

    Mybatis-Plus的條件構造器QueryWrapper和UpdateWrapper為開發(fā)者提供了強大、靈活的條件構建工具,能夠大大簡化數(shù)據(jù)庫操作的代碼,通過本文的介紹,讀者可以更加深入地理解這兩個條件構造器的使用方法,并在實際項目中靈活應用,感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • Spring?Cloud?使用?Resilience4j?實現(xiàn)服務熔斷的方法

    Spring?Cloud?使用?Resilience4j?實現(xiàn)服務熔斷的方法

    服務熔斷是為了保護我們的服務,比如當某個服務出現(xiàn)問題的時候,控制打向它的流量,讓它有時間去恢復,或者限制一段時間只能有固定數(shù)量的請求打向這個服務,這篇文章主要介紹了Spring?Cloud?使用?Resilience4j?實現(xiàn)服務熔斷,需要的朋友可以參考下
    2022-12-12
  • java多線程使用mdc追蹤日志方式

    java多線程使用mdc追蹤日志方式

    這篇文章主要介紹了java多線程使用mdc追蹤日志方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java怎樣判斷堆區(qū)中的對象可以被回收了

    Java怎樣判斷堆區(qū)中的對象可以被回收了

    文章介紹了Java垃圾回收機制的工作原理,主要通過引用計數(shù)法和可達性分析法來判斷對象是否可以被回收,引用計數(shù)法存在循環(huán)引用問題,而可達性分析法則使用GCRoot對象來判斷對象是否可達,從而決定是否回收,這兩種方法各有優(yōu)缺點,但Java最終采用了可達性分析法來實現(xiàn)垃圾回收
    2024-12-12
  • java中的final關鍵字詳解及實例

    java中的final關鍵字詳解及實例

    這篇文章主要介紹了 java中的final關鍵字詳解及實例的相關資料,需要的朋友可以參考下
    2017-03-03
  • javaweb學習總結(jié)——使用JDBC處理MySQL大數(shù)據(jù)

    javaweb學習總結(jié)——使用JDBC處理MySQL大數(shù)據(jù)

    本篇文章主要介紹了JDBC處理MySQL大數(shù)據(jù),有時是需要用程序把大文本或二進制數(shù)據(jù)直接保存到數(shù)據(jù)庫中進行儲存的,非常具有實用價值,需要的朋友可以參考下。
    2016-11-11
  • JBoss5.x下配置Log4j方法介紹

    JBoss5.x下配置Log4j方法介紹

    這篇文章主要介紹了JBoss5.x下配置Log4j方法介紹,小編覺得挺不錯的,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • Java實現(xiàn)從jar包中讀取指定文件的方法

    Java實現(xiàn)從jar包中讀取指定文件的方法

    這篇文章主要介紹了Java實現(xiàn)從jar包中讀取指定文件的方法,涉及java針對jar文件的讀取及查找相關操作技巧,需要的朋友可以參考下
    2017-08-08
  • 徹底理解Spring注解@Autowired實現(xiàn)原理

    徹底理解Spring注解@Autowired實現(xiàn)原理

    這篇文章主要為大家詳細的介紹了Spring注解@Autowired實現(xiàn)的原理,縝密的邏輯分析,實踐應用示例操作說明,讓大家徹底的理解Spring注解@Autowired背后實現(xiàn)原理
    2022-03-03
  • SpringBoot整合Quartz實現(xiàn)動態(tài)配置的代碼示例

    SpringBoot整合Quartz實現(xiàn)動態(tài)配置的代碼示例

    這篇文章將介紹如何把Quartz定時任務做成接口,實現(xiàn)以下功能的動態(tài)配置添加任務,修改任務,暫停任務,恢復任務,刪除任務,任務列表,任務詳情,文章通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2023-07-07

最新評論

东山县| 临夏市| 汉中市| 尼勒克县| 商城县| 调兵山市| 徐州市| 阿拉善左旗| 伊吾县| 新龙县| 美姑县| 道真| 龙陵县| 彭州市| 逊克县| 赤城县| 景东| 修武县| 泽普县| 阿尔山市| 永新县| 绥滨县| 景泰县| 广灵县| 渝中区| 甘泉县| 雷波县| 微山县| 鸡西市| 南宫市| 苏尼特左旗| 太湖县| 贡嘎县| 道孚县| 正定县| 鞍山市| 太和县| 海南省| 甘德县| 车致| 南投县|