偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

實(shí)時(shí)數(shù)據(jù)推送并非只有WebSocket一種選擇

開(kāi)發(fā) 前端
默認(rèn)是“message”事件,因?yàn)樗梢圆东@沒(méi)有 event 字段的事件, * 以及具有特定類(lèi)型 `event:message` 的事件。* 它不會(huì)觸發(fā)任何其他類(lèi)型的事件。

環(huán)境:SpringBoot2.7.16

概述

在Web應(yīng)用中,有幾種實(shí)時(shí)數(shù)據(jù)推送的選擇方案,包括SSE(Server-Sent Events)、WebSocket、長(zhǎng)輪詢(xún)等。

SSE是一種基于HTTP協(xié)議的服務(wù)器向客戶(hù)端推送數(shù)據(jù)的技術(shù)。它的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單、輕量級(jí),對(duì)現(xiàn)有服務(wù)器軟件兼容性好。但是,由于SSE是單向通信模型,只能由服務(wù)器向客戶(hù)端推送數(shù)據(jù),對(duì)于需要客戶(hù)端向服務(wù)器發(fā)送數(shù)據(jù)的場(chǎng)景,SSE就無(wú)法滿(mǎn)足需求。

WebSocket是一種雙向通信模型,允許客戶(hù)端和服務(wù)器之間互相發(fā)送消息。它的優(yōu)點(diǎn)是實(shí)時(shí)性強(qiáng)、延遲低,但是需要服務(wù)器端支持對(duì)應(yīng)的協(xié)議棧,實(shí)現(xiàn)起來(lái)相對(duì)復(fù)雜一些。

長(zhǎng)輪詢(xún)是對(duì)短輪詢(xún)的一種改進(jìn)版本,通過(guò)在盡可能減少對(duì)服務(wù)器資源浪費(fèi)的同時(shí),保證消息的相對(duì)實(shí)時(shí)性。長(zhǎng)輪詢(xún)?cè)诳蛻?hù)端發(fā)起請(qǐng)求時(shí),服務(wù)器會(huì)保持連接打開(kāi),等待一定時(shí)間后再返回響應(yīng)。這樣可以減少客戶(hù)端頻繁的請(qǐng)求,節(jié)省帶寬和服務(wù)器資源。但是,如果服務(wù)器沒(méi)有新的消息產(chǎn)生,客戶(hù)端會(huì)一直等待響應(yīng),實(shí)時(shí)性就會(huì)受到一定影響。

根據(jù)實(shí)際應(yīng)用場(chǎng)景和需求,可以選擇適合的實(shí)時(shí)數(shù)據(jù)推送方案。如果只需要服務(wù)器向客戶(hù)端推送數(shù)據(jù),且對(duì)實(shí)時(shí)性要求不是特別高,可以選擇SSE。如果需要客戶(hù)端向服務(wù)器發(fā)送數(shù)據(jù),或者對(duì)實(shí)時(shí)性要求較高,可以選擇WebSocket或長(zhǎng)輪詢(xún)。當(dāng)然,也可以根據(jù)實(shí)際情況將這幾種方案結(jié)合起來(lái)使用,以滿(mǎn)足不同的需求。

SSE與WebSocket對(duì)比

SSE(Server-Sent Events)和WebSocket都是用于實(shí)現(xiàn)實(shí)時(shí)通信的技術(shù),存在關(guān)鍵差異。

通信模型:SSE是單向通信模型,只能由服務(wù)器向客戶(hù)端推送數(shù)據(jù)。而WebSocket是雙向通信模型,客戶(hù)端和服務(wù)器可以互相發(fā)送消息。

連接性:SSE使用長(zhǎng)輪詢(xún)或HTTP流技術(shù),需要頻繁地發(fā)起HTTP請(qǐng)求來(lái)獲取數(shù)據(jù)。而 WebSocket只需在握手階段建立一次連接,然后保持連接打開(kāi),減少了頻繁建立連接的開(kāi)銷(xiāo)。

實(shí)時(shí)性:WebSocket提供了更低的延遲和更高的實(shí)時(shí)性,因?yàn)樗С蛛p向通信,可以立即將數(shù)據(jù)推送給客戶(hù)端。SSE雖然也可以實(shí)現(xiàn)實(shí)時(shí)性,但由于其單向通信模型,需要服務(wù)器定期發(fā)送數(shù)據(jù)。

協(xié)議特性:SSE是部署在HTTP協(xié)議之上的,現(xiàn)有的服務(wù)器軟件都支持。而WebSocket是一個(gè)新的協(xié)議,需要服務(wù)器端支持對(duì)應(yīng)的協(xié)議棧。

復(fù)雜性:SSE相對(duì)WebSocket來(lái)說(shuō)更輕量級(jí),實(shí)現(xiàn)更簡(jiǎn)單。WebSocket協(xié)議較復(fù)雜,實(shí)現(xiàn)相對(duì)困難一些。

總體來(lái)說(shuō),SSE和WebSocket都有各自的優(yōu)點(diǎn)和適用場(chǎng)景。SSE輕量級(jí)且對(duì)現(xiàn)有服務(wù)器軟件兼容性好,而WebSocket則提供了更強(qiáng)的雙向通信能力和更高的實(shí)時(shí)性。

SSE簡(jiǎn)介

SSE(Server-Sent Events)是一種用于實(shí)現(xiàn)服務(wù)器向客戶(hù)端實(shí)時(shí)推送數(shù)據(jù)的Web技術(shù)。與傳統(tǒng)的輪詢(xún)和長(zhǎng)輪詢(xún)相比,SSE提供了更高效和實(shí)時(shí)的數(shù)據(jù)推送機(jī)制。

SSE基于HTTP協(xié)議,允許服務(wù)器將數(shù)據(jù)以事件流(Event Stream)的形式發(fā)送給客戶(hù)端??蛻?hù)端通過(guò)建立持久的HTTP連接,并監(jiān)聽(tīng)事件流,可以實(shí)時(shí)接收服務(wù)器推送的數(shù)據(jù)。

SSE的主要特點(diǎn)包括:

簡(jiǎn)單易用:SSE使用基于文本的數(shù)據(jù)格式,如純文本、JSON等,使得數(shù)據(jù)的發(fā)送和解析都相對(duì)簡(jiǎn)單。

單向通信:SSE支持服務(wù)器向客戶(hù)端的單向通信,服務(wù)器可以主動(dòng)推送數(shù)據(jù)給客戶(hù)端。

實(shí)時(shí)性:SSE建立長(zhǎng)時(shí)間的連接,使得服務(wù)器可以實(shí)時(shí)地將數(shù)據(jù)推送給客戶(hù)端,而無(wú)需客戶(hù)端頻繁地發(fā)起請(qǐng)求。

服務(wù)端開(kāi)發(fā)

依賴(lài)管理

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

配置文件

spring:
  mvc:
    static-path-pattern: /**
  web:
    resources:
      #靜態(tài)文件目錄index.html
      static-locations: classpath:/templates/

接口開(kāi)發(fā)

@RestController
@RequestMapping("/sse")
public class SseController {
  
  // 該集合用來(lái)管理所有客戶(hù)端的連接
  private final Map<String, SseEmitter> sse = new ConcurrentHashMap<>() ;


  // 創(chuàng)建連接接口,同時(shí)指定了消息類(lèi)型為text/event-stream
  @GetMapping(path="/events/{id}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
  public SseEmitter createConnect(@PathVariable("id") String id) throws IOException {
    SseEmitter emitter = new SseEmitter(0L);
    // 每一個(gè)客戶(hù)端保存到Map中
    sse.put(id, emitter) ;
    // 當(dāng)發(fā)生錯(cuò)誤的回調(diào)
    emitter.onError(ex -> {
      System.err.printf("userId: %s, error: %s%n", id, ex.getMessage()) ;
      sse.remove(id) ;
    }) ;
   // 異步請(qǐng)求完成后的回調(diào)
    emitter.onCompletion(() -> {
      sse.remove(id) ;
      System.out.printf("%s, 請(qǐng)求完成...") ;
    }) ;
    // 異步請(qǐng)求超時(shí)回調(diào)
    emitter.onTimeout(() -> {
      System.err.println("超時(shí)...") ;
    }) ;
    return emitter;
  }
  
  // 該接口用來(lái)進(jìn)行消息的發(fā)送
  // 由客戶(hù)端發(fā)起請(qǐng)求,然后根據(jù)id獲取相應(yīng)的SseEmitter進(jìn)行消息的發(fā)送
  @GetMapping("/sender/{id}")
  public String sender(@PathVariable("id") String id) throws Exception {
    SseEmitter emitter = this.sse.get(id) ;
    if (emitter != null) {
      try {
        emitter.send( "隨機(jī)消息 - " + new Random().nextInt(10000000)) ;
      } catch (Exception e) {
        System.err.println("%s%n", e.getMessage()) ;
      }
    }
    return "success" ;
  }
}

前端開(kāi)發(fā)

前端比較簡(jiǎn)單就是一個(gè)index.html頁(yè)面

<html>
  <head>
  <title>SSE</title>
</head>
<body>
  <button type="button" onclick="closeSse()">Close</button>
  <hr style="margin: 2px; padding: 0px 0px;"/>
  <ul id="list"></ul>
</body>
<script>
  const evtSource = new EventSource(`/sse/events/${Date.now()}`) ;
  evtSource.onmessage = (event) => {
    const newElement = document.createElement("li") ;
    const eventList = document.getElementById("list") ;
    newElement.innerHTML = "接收到消息: " + event.data ;
    eventList.appendChild(newElement) ;
  };
  evtSource.onopen = (event) => {
    console.log('建立連接...')
  };
  evtSource.onerror = (event) => {
    console.error("發(fā)生錯(cuò)誤:", event) ;
  };
  function closeSse() {
    evtSource.close() ;
  }
</script>
</html>

以上就是前后端的開(kāi)發(fā),代碼非常的簡(jiǎn)單;也就簡(jiǎn)單的實(shí)現(xiàn)了由服務(wù)端實(shí)時(shí)數(shù)據(jù)推送。

EventSource對(duì)象的readyState有3個(gè)狀態(tài)值:

0 — connecting

1 — open

2 — closed

測(cè)試

圖片圖片

調(diào)用消息發(fā)送接口

圖片圖片


圖片圖片

自定義事件類(lèi)型

修改消息發(fā)送接口

@GetMapping("/sender/{id}")
  public String sender(@PathVariable("id") String id) throws Exception {
    SseEmitter emitter = this.sse.get(id) ;
    if (emitter != null) {
      SseEventBuilder builder = SseEmitter.event() ;
      // 指定事件類(lèi)型
      builder.name("chat") ;
      String msg = "隨機(jī)消息 - " + new Random().nextInt(10000000);
      builder.data(msg) ;
      try {
        emitter.send(builder) ;
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    return "success" ;
  }

前端監(jiān)聽(tīng)具體事件類(lèi)型消息

// 監(jiān)聽(tīng)指定事件類(lèi)型消息
evtSource.addEventListener("chat", (event) => {
  const newElement = document.createElement("li");
  const eventList = document.getElementById("list");


  newElement.innerHTML = "chat message: " + event.data;
  eventList.appendChild(newElement);
});

注意:默認(rèn)是“message”事件,因?yàn)樗梢圆东@沒(méi)有 event 字段的事件, * 以及具有特定類(lèi)型 `event:message` 的事件。* 它不會(huì)觸發(fā)任何其他類(lèi)型的事件。

責(zé)任編輯:武曉燕 來(lái)源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2024-04-01 08:38:57

Spring@AspectAOP

2023-11-28 09:44:10

2024-09-02 09:31:19

2019-08-20 14:13:12

工業(yè)物聯(lián)網(wǎng)IIOT藍(lán)牙

2020-11-12 18:48:54

安全電商數(shù)據(jù)中臺(tái)

2016-07-29 00:43:22

數(shù)據(jù)驅(qū)動(dòng)

2021-09-10 09:09:58

ARTIF威脅智能框架安全工具

2016-12-23 14:58:58

容器WebSocketDocker Remo

2014-02-25 10:11:00

2020-12-09 10:15:34

Pythonweb代碼

2021-07-30 16:09:18

加密貨幣比特幣貨幣

2025-09-08 03:15:00

JavaScript數(shù)據(jù)流接口

2022-06-06 15:44:24

大數(shù)據(jù)數(shù)據(jù)分析思維模式

2022-07-07 10:33:27

Python姿勢(shì)代碼

2020-12-23 10:10:23

Pythonweb代碼

2022-06-22 09:44:41

Python文件代碼

2020-05-29 17:10:15

數(shù)據(jù)架構(gòu)數(shù)據(jù)一切數(shù)據(jù)體系

2020-04-28 11:04:51

數(shù)據(jù)架構(gòu)互聯(lián)網(wǎng)Flink

2021-07-22 18:29:58

AI

2025-01-15 12:00:00

Java線(xiàn)程編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)