国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SSE:后端向前端發(fā)送消息(springboot SseEmitter)

這篇具有很好參考價值的文章主要介紹了SSE:后端向前端發(fā)送消息(springboot SseEmitter)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

背景

有一個項目,前端vue,后端springboot?,F(xiàn)在需要做一個功能:用戶在使用系統(tǒng)的時候,管理員發(fā)布公告,則使用系統(tǒng)的用戶可以看到該公告。
基于此,一個簡單的方案:前端使用JS方法setInterval,重復(fù)調(diào)用后端公告獲取接口。此方法有幾點缺陷:

  • 循環(huán)調(diào)用的時間間隔不好確定:太長了,獲取公告的時效有延遲;太短了,給服務(wù)器造成壓力,很多請求都是無用的(公告發(fā)布的時間不定,很可能幾天都沒有新公告);
  • token的續(xù)期問題:項目中,前端請求,需要帶上token,token有過期時間,如果用戶一直使用(前后端有交互),會無感續(xù)期。如果有這種定時循環(huán)和后端交互的場景,就會造成token用不過期(循環(huán)的調(diào)用會觸發(fā)續(xù)期),當(dāng)然,可以在續(xù)期中,排除某個場景的請求,但是這樣的設(shè)計不好,因為這種場景太多了,就會造成維護上的困難。

因此就想到了,如果后端主動向前端推送消息,這個問題就可以完美解決。

方案

有兩種方案可以實現(xiàn)后端向前端推送消息:

  1. 使用websocket;
  2. 使用sse;

這里介紹SSE的方式(如果系統(tǒng)中對這種消息的準(zhǔn)確性和可靠性有嚴(yán)格的要求,則使用websocket,websocket的使用相對復(fù)雜的多);
如果想了解SSE的詳細基礎(chǔ)知識,可以參考阮一峰老師的這篇文章:Server-Sent Events 教程

SSE后端代碼

SpringMVC中,已經(jīng)集成了該功能,所以無需額外引入jar包,直接上代碼:

@RestController
@RequestMapping("/notice")
public class NoticeController {

    @Autowired
    private NoticeService noticeService;

    @GetMapping(path = "createSseEmitter")
    public SseEmitter createSseEmitter(String id) {
        return noticeService.createSseEmitter(id);
    }

    @PostMapping(path = "sendMsg")
    public boolean sendMsg(String id, String content) {
        noticeService.sendMsg(id, content);
        return true;
    }

}

@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    @Autowired
    @Qualifier("sseEmitterCacheService")
    private CacheService<SseEmitter> sseEmitterCacheService;

    @Override
    public SseEmitter createSseEmitter(String clientId) {
        if (StringUtil.isBlank(clientId)) {
            clientId = UUID.randomUUID().toString().replace("-", "");
        }
        SseEmitter sseEmitter = sseEmitterCacheService.getCache(clientId);
        log.info("獲取SSE,id={}", clientId);
        final String id = clientId;
        sseEmitter.onCompletion(() -> {
            log.info("SSE已完成,關(guān)閉連接 id={}", id);
            sseEmitterCacheService.deleteCache(id);
        });
        return sseEmitter;
    }
    @Override
    public void sendMsg(String clientId, String content) {
        if (sseEmitterCacheService.hasCache(clientId)) {
            SseEmitter sseEmitter = sseEmitterCacheService.getCache(clientId);
            try {
                sseEmitter.send(content);
            } catch (IOException e) {
                log.error("發(fā)送消息失敗:{}", e.getMessage(), e);
                throw new BusinessRuntimeExcepption(CustomExcetionConstant.IO_ERR, "發(fā)送消息失敗", e);
            }
        } else {
            log.error("SSE對象不存在");
            throw new BusinessRuntimeExcepption("SSE對象不存在");
        }
    }
}

這里,只列出了核心的代碼,簡而言之,需要做到兩點即可:

  1. 前端首先是發(fā)起一個請求,創(chuàng)建SseEmitter,即createSseEmitter方法,該方法必須返回一個SseEmitter對象;
  2. 返回的SseEmitter,后端必須要緩存起來(我用的是ehcache,也可以直接定義一個map來緩存);

為什么要這么做?看下文,后端代碼一起來分析就明白了。

前端代碼

由于,我請求該接口,需要帶上token,所以直接使用EventSource不行,另外這個IE也不支持。所以選擇了一個工具:event-source-polyfill。

  1. 先安裝event-source-polyfill
npm install event-source-polyfill
  1. 然后使用:
import { EventSourcePolyfill } from "event-source-polyfill";
  created() {
    let _this = this;
    this.source = new EventSourcePolyfill(
      "/" +
        process.env.VUE_APP_MANAGER_PRE_API_URL +
        "/notice/createSseEmitter?id=" +
        uuid(),
      {
        headers: {
          [process.env.VUE_APP_OAUTH_AUTHORIZATION]: store.getters.getToken,
        },
        //重連時間間隔,單位:毫秒,默認(rèn)45000毫秒,這里設(shè)置為10分鐘
        heartbeatTimeout: 10 * 60 * 1000,
      }
    );

    this.source.onopen = () => {
      console.log("NOTICE建立連接");
    };
    this.source.onmessage = (e) => {
      _this.scrollMessage = e.data;
      console.log("NOTICE接收到消息");
    };
    this.source.onerror = (e) => {
      if (e.readyState == EventSource.CLOSED) {
        console.log("NOTICE連接關(guān)閉");
      } else if (this.source.readyState == EventSource.CONNECTING) {
        console.log("NOTICE正在重連");
        //重新設(shè)置header
        this.source.headers = {
          [process.env.VUE_APP_OAUTH_AUTHORIZATION]: store.getters.getToken,
        };
      } else {
        console.log(e);
      }
    };
  },

有幾點說明:

  • new EventSourcePolyfill中,可以帶入header
  • heartbeatTimeout是一個心跳時間,默認(rèn)情況下間隔heartbeatTimeout后,會觸發(fā)重新連接后端接口;
  • this.source.headers,該行的作用是在重連的時候重新設(shè)置header,如果不這樣,那么重連的時候,用的參數(shù)信息,還是和最開始的一樣(包括本例中url中的id)。而由于我的項目中,如果token其他操作觸發(fā)了刷新token,則有效token可能會變,所以,這里取緩存中放置的token,而不應(yīng)該使用最初的token。
    好了,這樣就基本實現(xiàn)了我們所需要的功能了。

特別注意

前端配置了代理,所以一直收不到后端發(fā)送的消息,嘗試加入以下參數(shù):

  devServer: {
    compress:false,
    …………
}

問題

之前在寫后端的時候提到了兩個問題:為什么要返回SseEmitter對象?為什么要緩存SseEmitter對象?
其實看過SSE的原理,都應(yīng)該明白:這就是一個長連接,前端調(diào)用創(chuàng)建SseEmitter對象的接口,雖然接口返回了,但是并未結(jié)束(這就是為什么要返回SseEmitter對象,如果返回的是一個其他對象,就和普通的接口沒兩樣了, 該接口就直接結(jié)束了),請看下截圖:
sseemitter,WEB,VUE,SpringBoot,前端,spring boot,java,web
發(fā)起請求之后,一直是待處理,并未結(jié)束,10分鐘之后,該請求被取消(前端設(shè)置的重連),然后重新發(fā)起連接,重新發(fā)起的連接也是在等待中。只有接收到消息后,這個請求的狀態(tài)碼才是200,但是這個時候才連接已經(jīng)建立好了。其中的細節(jié),這里不做講述。
所以,如果再使用SseEmitter對象發(fā)送消息,則前端就可以收到對象的消息了(即實現(xiàn)后端向前端發(fā)送消息)。這里使用的SseEmitter對象,就是createSseEmitter接口返回的對象(也就是使用哪個SseEmitter對象,就可以向哪個前端發(fā)送消息)。這也就是為什么要緩存SseEmitter對象的原因了。

效果

通過調(diào)用發(fā)送消息接口,前端即可立即展示發(fā)送的消息:
sseemitter,WEB,VUE,SpringBoot,前端,spring boot,java,web文章來源地址http://www.zghlxwxcb.cn/news/detail-788403.html

到了這里,關(guān)于SSE:后端向前端發(fā)送消息(springboot SseEmitter)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java:SpringBoot整合WebSocket實現(xiàn)服務(wù)端向客戶端推送消息

    Java:SpringBoot整合WebSocket實現(xiàn)服務(wù)端向客戶端推送消息

    思路: 后端通過websocket向前端推送消息,前端統(tǒng)一使用http協(xié)議接口向后端發(fā)送數(shù)據(jù) 本文僅放一部分重要的代碼,完整代碼可參看github倉庫 websocket 前端測試 :http://www.easyswoole.com/wstool.html 依賴 項目目錄 完整依賴 配置 WebSocketServer.java 前端頁面 websocket.html 前端邏輯 index.js 參

    2024年02月04日
    瀏覽(29)
  • SSE與WebSocket分別實現(xiàn)服務(wù)器發(fā)送消息通知(Golang、Gin)

    SSE與WebSocket分別實現(xiàn)服務(wù)器發(fā)送消息通知(Golang、Gin)

    服務(wù)端推送,也稱為消息推送或通知推送,是一種允許應(yīng)用服務(wù)器主動將信息發(fā)送到客戶端的能力,為客戶端提供了實時的信息更新和通知,增強了用戶體驗。 服務(wù)端推送的背景與需求主要基于以下幾個訴求: 實時通知:在很多情況下,用戶期望實時接收到應(yīng)用的通知,如

    2024年02月03日
    瀏覽(28)
  • java socket Server TCP服務(wù)端向指定客戶端發(fā)送消息;可查看、斷開指定連接的客戶端;以及設(shè)置客戶端最大可連接數(shù)量。

    首先需要知道java里如何創(chuàng)建一個Socket服務(wù)器端。 提示:注意server.accept()方法調(diào)用會阻塞,只有新的客戶端連接后才返回一個新的socket對象。如果一直未連接那么會一直處于阻塞狀態(tài) 了解了如何創(chuàng)建一個socket服務(wù)器端后。那么如何實現(xiàn)給指定的連接客戶端發(fā)送消息呢?首先我

    2024年02月11日
    瀏覽(24)
  • 獲取第三方接口的EventStream返回給前端,SpringBoot+Vue+WebFlux+SseEmitter

    后端: 其中曾踩了一些坑: 1.原本是bodyToFlux(String.class),結(jié)果沒有返回也沒有報錯,排查了許久,最終改成bodyToFlux(byte[].class) 2.原本未使用Mono.fromCallable進行異步請求,結(jié)果其實是一次獲取到完整的流再給前端,與長連接實時輸出信息相悖。實際應(yīng)該把SseEmitter返回給前端,異

    2024年03月19日
    瀏覽(91)
  • 前端實現(xiàn)消息推送、即時通信、SSE、WebSocket、http簡介

    前端實現(xiàn)消息推送、即時通信、SSE、WebSocket、http簡介

    服務(wù)端主動向客戶端推送消息,使客戶端能夠即時接收到信息。 場景 頁面接收到點贊,消息提醒 聊天功能 彈幕功能 實時更新數(shù)據(jù)功能 短輪詢 瀏覽器(客戶端)每隔一段時間向服務(wù)器發(fā)送http請求,服務(wù)器端在收到請求后,不論是否有數(shù)據(jù)更新,都直接進行響應(yīng)。 本質(zhì):客

    2024年02月16日
    瀏覽(19)
  • SSE實現(xiàn)消息實時推送,前端漸進式學(xué)習(xí)、實踐,真香

    SSE(Server Sent Event),直譯為服務(wù)器發(fā)送事件,顧名思義,也就是客戶端可以獲取到服務(wù)器發(fā)送的事件。我們常見的 http 交互方式是客戶端發(fā)起請求,服務(wù)端響應(yīng),然后一次請求完畢;但是在 sse 的場景下,客戶端發(fā)起請求,連接一直保持,服務(wù)端有數(shù)據(jù)就可以返回數(shù)據(jù)給客戶端

    2024年02月21日
    瀏覽(20)
  • Springboot集成SSE實現(xiàn)消息推送之單工通信

    Springboot集成SSE實現(xiàn)消息推送之單工通信

    通常在一些web項目中,會涉及到想客戶端推送消息,常見的有Ajax輪詢、webSocket,本篇文章主要使用Springboot集成SSE實現(xiàn)向客戶端持續(xù)推送信息。 服務(wù)發(fā)送事件SSE(Sever-Sent Event),就是基于 HTTP 的技術(shù),瀏覽器向服務(wù)器發(fā)送一個保持長連接HTTP請求,服務(wù)器單向地向客戶端以流形

    2024年01月17日
    瀏覽(25)
  • 使用post請求建立長連接實現(xiàn)sse,接收后端主動發(fā)來的消息,實現(xiàn)chat-gpt的彈字效果,EventSource的應(yīng)用

    使用post請求建立長連接實現(xiàn)sse,接收后端主動發(fā)來的消息,實現(xiàn)chat-gpt的彈字效果,EventSource的應(yīng)用

    每日雞湯:每個你想要學(xué)習(xí)的瞬間都是未來的你向自己求救 最近在做一個chat相關(guān)的功能,然后由于接口返回特別特別慢,所以需要搞一個慢慢等待的效果,就是接口一個單詞一個單詞的返回,然后前端收到一個展示一個,提升用戶體驗。 說實話我是第一次做這類需求,他們

    2024年02月09日
    瀏覽(27)
  • SpringBoot使用SSE進行實時通知前端

    SpringBoot使用SSE進行實時通知前端

    項目有個需求是要實時通知前端,告訴前端這個任務(wù)加載好了。然后想了2個方案,一種是用websocket進行長連接,一種是使用SSE(Sever Send Event),是HTTP協(xié)議中的一種,Content-Type為text/event-stream,能夠保持長連接。 websocket是前端既能向后端發(fā)送消息,后端也能向前端發(fā)送消息。

    2024年02月08日
    瀏覽(23)
  • javaWEB消息推送之 WebSocket和SseEmitter

    用途 實時獲取服務(wù)端的最新數(shù)據(jù) 查看調(diào)度任務(wù)的進度和執(zhí)行狀態(tài) 用戶感知:修改數(shù)據(jù)后,相關(guān)用戶收到信息 提升用戶體驗:耗時業(yè)務(wù)異步處理(Excel導(dǎo)入導(dǎo)出,復(fù)雜計算) 前端輪詢 這種方式實現(xiàn)簡單,前端通過 setInterval 定時去請求接口來獲取最新的數(shù)據(jù),當(dāng)實時性要求不

    2024年01月24日
    瀏覽(12)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包