欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot集成SSE實現(xiàn)單工通信消息推送流程詳解

 更新時間:2022年11月16日 16:30:12   作者:三省同學(xué)  
SSE簡單的來說就是服務(wù)器主動向前端推送數(shù)據(jù)的一種技術(shù),它是單向的,也就是說前端是不能向服務(wù)器發(fā)送數(shù)據(jù)的。SSE適用于消息推送,監(jiān)控等只需要服務(wù)器推送數(shù)據(jù)的場景中,下面是使用Spring Boot來實現(xiàn)一個簡單的模擬向前端推動進度數(shù)據(jù),前端頁面接受后展示進度條

前言

通常在一些web項目中,會涉及到想客戶端推送消息,常見的有Ajax輪詢、webSocket,本篇文章主要使用Springboot集成SSE實現(xiàn)向客戶端持續(xù)推送信息。

SSE簡介

服務(wù)發(fā)送事件SSE(Sever-Sent Event),就是基于 HTTP 的技術(shù),瀏覽器向服務(wù)器發(fā)送一個保持長連接HTTP請求,服務(wù)器單向地向客戶端以流形式持續(xù)傳輸數(shù)據(jù) 。這樣可以節(jié)約網(wǎng)絡(luò)資源,不需要建立新連接。

優(yōu)點

服務(wù)端不需要其他的類庫,開發(fā)難度較低。

不用每次建立新連接,延遲較低。 數(shù)據(jù)通過簡單且廣泛使用的HTTP協(xié)議而不是專有協(xié)議進行同步。

對重新建立連接和事件ID功能的內(nèi)置支持。

對于利用單向通信的應(yīng)用程序和服務(wù)非常有用。

缺點

客戶端越多連接越多,會占用服務(wù)器大量內(nèi)存和連接數(shù)。

SSE只支持UTF-8編碼,不支持二進制數(shù)據(jù)。

對最大打開連接數(shù)的嚴格限制可能使事情變得困難,每個瀏覽器都設(shè)置了限制。

SSE是單向的。

Springboot集成SSE簡約版

客戶端發(fā)送請求到服務(wù)端,服務(wù)端以流的形式不斷向客戶端推送數(shù)據(jù)示例,增加帥氣值。

xml依賴:

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

html代碼:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Springboot集成SSE簡約版</title>
    <script type="text/javascript">
        let source = new EventSource('/get');
        source.onmessage = function (event) {
            console.info(event.data);
            document.getElementById('text').innerText = event.data
        };
    </script>
</head>
<body>
<div id="text"></div>
</body>
</html>

后端代碼:

   @RequestMapping(value = "/get", produces = "text/event-stream;charset=UTF-8")
    public void push(HttpServletResponse response) {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("utf-8");
        int i = 0;
        while (true) {
            try {
                Thread.sleep(1000);
                PrintWriter pw = response.getWriter();
                //注意返回數(shù)據(jù)必須以data:開頭,"\n\n"結(jié)尾
                pw.write("data:xdm帥氣值加" + i + "\n\n");
                pw.flush();
                //檢測異常時斷開連接
                if (pw.checkError()) {
                    log.error("客戶端斷開連接");
                    return;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            i++;
        }
    }

效果:

Springboot集成SSE升級版

演示SSE的連接建立、接收數(shù)據(jù)和異常情況監(jiān)聽處理。

注:若瀏覽器不兼容在頁面引入evensource.js。

<script src=/eventsource-polyfill.js></script>

客戶端代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> Springboot集成SSE升級版</title>
</head>
<script>
    let source = null;
    const clientId = new Date().getTime();
    if (!!window.EventSource) {
        source = new EventSource('/sse/create?clientId=' + clientId);
    	//建立連接
        source.onopen = function (event) {
            setMessageInnerHTML("建立連接" + event);
        }
        //接收數(shù)據(jù)
        source.onmessage = function (event) {
            setMessageInnerHTML(event.data);
        }
        //錯誤監(jiān)聽
        source.onerror = function (event) {
            if (event.readyState === EventSource.CLOSED) {
                setMessageInnerHTML("連接關(guān)閉");
            } else {
                console.log(event);
            }
        }
    } else {
        setMessageInnerHTML("瀏覽器不支持SSE");
    }
    window.onbeforeunload = function () {
        close();
    };
    // 關(guān)閉
    function close() {
        source.close();
        const httpRequest = new XMLHttpRequest();
        httpRequest.open('GET', '/sse/close/?clientId=' + clientId, true);
        httpRequest.send();
        console.log("close");
    }
    // 顯示消息
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('text').innerHTML += innerHTML + '<br/>';
    }
</script>
<body>
<button onclick="close()">關(guān)閉連接</button>
<div id="text"></div>
</body>
</html>

服務(wù)端代碼:

private static Map<String, SseEmitter> cache = new ConcurrentHashMap<>();
String clientId;
int sseId;
@GetMapping("/create")
public SseEmitter create(@RequestParam(name = "clientId", required = false) String clientId) {
    // 設(shè)置超時時間,0表示不過期。默認30000毫秒
    //可以在客戶端一直斷網(wǎng)、直接關(guān)閉頁面但未提醒后端的情況下,服務(wù)端在一定時間等待后自動關(guān)閉網(wǎng)絡(luò)連接
    SseEmitter sseEmitter = new SseEmitter(0L);
    // 是否需要給客戶端推送ID
    if (Strings.isBlank(clientId)) {
        clientId = UUID.randomUUID().toString();
    }
    this.clientId = clientId;
    cache.put(clientId, sseEmitter);
    log.info("sse連接,當(dāng)前客戶端:{}", clientId);
    return sseEmitter;
}
@Scheduled(cron = "0/3 * *  * * ? ")
public void pushMessage() {
    try {
        sseId++;
        SseEmitter sseEmitter = cache.get(clientId);
        sseEmitter.send(
                SseEmitter
                        .event()
                        .data("帥氣值暴增" + sseId)
                        .id("" + sseId)
                        .reconnectTime(3000)
        );
    } catch (Exception e) {
        log.error(e.getMessage());
        sseId--;
    }
}
@GetMapping("/close")
public void close(String clientId) {
    SseEmitter sseEmitter = cache.get(clientId);
    if (sseEmitter != null) {
        sseEmitter.complete();
        cache.remove(clientId);
    }
}

方法參數(shù)說明:

 SseEmitter
          .event()
          .data("帥氣值暴增" + sseId)
          .id("" + sseId)
          .reconnectTime(3000)

SseEmitter.event()

用來得到一個記錄數(shù)據(jù)的容器。

.data("帥氣值暴增" + sseId)

發(fā)送給客戶端的數(shù)據(jù)。

.id("" + sseId)

記錄發(fā)送數(shù)據(jù)的標識,服務(wù)端可以通過HttpServletRequest的請求頭中拿到這個id,判斷是否中間有誤漏發(fā)數(shù)據(jù)。

.reconnectTime(3000)

定義在網(wǎng)絡(luò)連接斷開后,客戶端向后端發(fā)起重連的時間間隔(以毫秒為單位)。

效果:

參考資料:

鏈接1

鏈接2

到此這篇關(guān)于Springboot集成SSE實現(xiàn)單工通信消息推送流程詳解的文章就介紹到這了,更多相關(guān)Springboot消息推送內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于令牌桶的限流器注解的簡單實現(xiàn)詳解

    基于令牌桶的限流器注解的簡單實現(xiàn)詳解

    令牌桶算法是一種常用的流量控制算法,用于限制請求或事件的發(fā)生速率,這篇文章主要介紹了如何基于令牌桶實現(xiàn)限流器注解,需要的可以參考一下
    2023-08-08
  • Java中extends一定是代表繼承嗎?

    Java中extends一定是代表繼承嗎?

    今天小編就為大家分享一篇關(guān)于Java中extends一定是代表繼承嗎?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • JVM內(nèi)存參數(shù)配置詳解

    JVM內(nèi)存參數(shù)配置詳解

    本文主要介紹了JVM內(nèi)存參數(shù)配置詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java設(shè)計模式筆記之抽象工廠代碼示例

    Java設(shè)計模式筆記之抽象工廠代碼示例

    這篇文章主要介紹了Java設(shè)計模式筆記之抽象工廠代碼示例,見解獨到,代碼詳細,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • 細品Java8中hashCode方法的使用

    細品Java8中hashCode方法的使用

    這篇文章主要介紹了細品Java8中hashCode方法的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • mybatis Reflector反射類的具體使用

    mybatis Reflector反射類的具體使用

    Reflector類是MyBatis反射模塊的核心,負責(zé)處理類的元數(shù)據(jù),以實現(xiàn)屬性與數(shù)據(jù)庫字段之間靈活映射的功能,本文主要介紹了mybatis Reflector反射類的具體使用,感興趣的可以了解一下
    2024-02-02
  • mybatisplus實現(xiàn)自動創(chuàng)建/更新時間的項目實踐

    mybatisplus實現(xiàn)自動創(chuàng)建/更新時間的項目實踐

    Mybatis-Plus提供了自動填充功能,可以通過實現(xiàn)MetaObjectHandler接口來實現(xiàn)自動更新時間的功能,本文就來介紹一下mybatisplus實現(xiàn)自動創(chuàng)建/更新時間的項目實踐,感興趣的可以了解下
    2024-01-01
  • java根據(jù)方法名稱取得反射方法的參數(shù)類型示例

    java根據(jù)方法名稱取得反射方法的參數(shù)類型示例

    利用java反射原理調(diào)用方法時,常先需要傳入方法參數(shù)數(shù)組才能取得方法。該方法參數(shù)數(shù)組采用動態(tài)取得的方式比較合適
    2014-02-02
  • MyBatis-Plus 查詢返回實體對象還是map

    MyBatis-Plus 查詢返回實體對象還是map

    這篇文章主要介紹了MyBatis-Plus 查詢返回實體對象還是map,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot基于自定義注解實現(xiàn)切面編程

    SpringBoot基于自定義注解實現(xiàn)切面編程

    這篇文章主要介紹了SpringBoot基于自定義注解實現(xiàn)切面編程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11

最新評論