Spring?Boot?3.4.3?基于?Spring?WebFlux?實(shí)現(xiàn)?SSE?功能(代碼示例)
在現(xiàn)代 Web 應(yīng)用開發(fā)中,實(shí)時(shí)數(shù)據(jù)推送已成為許多業(yè)務(wù)場(chǎng)景的核心需求,例如實(shí)時(shí)通知、股票價(jià)格更新或在線聊天等。傳統(tǒng)的輪詢方式效率低下,而 SSE(Server-Sent Events,服務(wù)器推送事件)作為 HTML5 提供的一種輕量級(jí)技術(shù),能夠通過單向長(zhǎng)連接實(shí)現(xiàn)服務(wù)器到客戶端的實(shí)時(shí)數(shù)據(jù)推送。Spring Boot 3.4.3 結(jié)合 Spring WebFlux,為開發(fā)者提供了響應(yīng)式編程能力,使得實(shí)現(xiàn) SSE 功能更加簡(jiǎn)單高效。本文將詳細(xì)介紹如何在 Spring Boot 3.4.3 中基于 Spring WebFlux 實(shí)現(xiàn) SSE 功能,并提供完整的代碼示例,助你在企業(yè)級(jí)應(yīng)用中快速落地實(shí)時(shí)推送需求。
1. SSE 簡(jiǎn)介
1.1 什么是 SSE?
SSE(Server-Sent Events)是一種基于 HTTP 協(xié)議的服務(wù)器推送技術(shù),允許服務(wù)器主動(dòng)向客戶端發(fā)送數(shù)據(jù)??蛻舳送ㄟ^建立長(zhǎng)連接接收服務(wù)器推送的事件流,適用于需要實(shí)時(shí)更新的場(chǎng)景。與 WebSocket 相比,SSE 是單向通信(僅服務(wù)器到客戶端),實(shí)現(xiàn)更簡(jiǎn)單,且瀏覽器原生支持。
1.2 SSE 的優(yōu)點(diǎn)
- 輕量級(jí):基于 HTTP,無需額外協(xié)議支持。
- 簡(jiǎn)單性:實(shí)現(xiàn)成本低,適合單向推送場(chǎng)景。
- 自動(dòng)重連:客戶端斷開后可自動(dòng)嘗試重連。
- 兼容性:HTML5 標(biāo)準(zhǔn),主流瀏覽器均支持。
1.3 適用場(chǎng)景
- 實(shí)時(shí)通知(如消息提醒)。
- 數(shù)據(jù)監(jiān)控(如服務(wù)器狀態(tài)更新)。
- 單向事件流(如日志推送)。
2. Spring WebFlux 簡(jiǎn)介
Spring WebFlux 是 Spring 5 引入的響應(yīng)式 Web 框架,與傳統(tǒng)的 Spring MVC 不同,它基于 Reactor 項(xiàng)目,支持異步非阻塞的編程模型。Spring Boot 3.4.3 默認(rèn)集成了 Spring WebFlux,使得開發(fā)者可以輕松構(gòu)建高并發(fā)、事件驅(qū)動(dòng)的應(yīng)用。結(jié)合 SSE,WebFlux 的 Flux 數(shù)據(jù)流非常適合處理實(shí)時(shí)推送需求。
3. 項(xiàng)目實(shí)戰(zhàn)
以下是基于 Spring Boot 3.4.3 和 Spring WebFlux 實(shí)現(xiàn) SSE 功能的完整步驟。
3.1 添加 Maven 依賴
在 pom.xml 中添加 Spring WebFlux 的依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
</parent>
<artifactId>springboot-sse</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
</project>說明:
spring-boot-starter-webflux提供了 WebFlux 的核心功能和 Reactor 依賴。- Spring Boot 3.4.3 使用 JDK 17,確保編譯器版本匹配。
3.2 創(chuàng)建 SSE 控制器
創(chuàng)建一個(gè)控制器,用于推送事件流:
package cn.joyous.sse.controller;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
/**
*/
@RestController
public class SSEController {
// 定義一個(gè)計(jì)數(shù)器,用于模擬數(shù)據(jù)變化
private final AtomicInteger counter = new AtomicInteger(0);
@GetMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<Integer>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(seq -> ServerSentEvent.<Integer>builder()
.id(String.valueOf(seq))
.event("message")
.data(counter.incrementAndGet())
.build());
}
}代碼說明:
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE):指定返回 SSE 事件流。Flux.interval(Duration.ofSeconds(1)):每秒生成一個(gè)事件。ServerSentEvent.builder():構(gòu)造 SSE 事件,包含id(事件標(biāo)識(shí))、event(事件類型)和data(推送數(shù)據(jù))。
3.3 前端頁(yè)面示例
創(chuàng)建一個(gè)簡(jiǎn)單的 HTML 頁(yè)面,用于接收 SSE 數(shù)據(jù):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SSE Demo</title>
</head>
<body>
<h1>SSE 數(shù)據(jù)推送</h1>
<div id="result"></div>
<script>
const eventSource = new EventSource("http://localhost:8080/sse");
eventSource.onmessage = function(event) {
document.getElementById("result").innerText += "收到數(shù)據(jù): " + event.data + "\n";
};
eventSource.onerror = function() {
console.log("SSE 連接失敗");
eventSource.close();
};
</script>
</body>
</html>保存為 sse.html,放置在 src/main/resources/static 目錄下。
3.4 啟動(dòng)與測(cè)試
- 啟動(dòng) Spring Boot 應(yīng)用。
- 在瀏覽器中訪問
http://localhost:8080/sse.html,你將看到頁(yè)面每秒更新一次計(jì)數(shù)器數(shù)據(jù)。 - 或者直接訪問
http://localhost:8080/sse,查看原始事件流:
id: 0 event: message data: 1 id: 1 event: message data: 2
4. 進(jìn)階功能(可選)
自定義事件類型
修改控制器支持多種事件:
@GetMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(seq -> ServerSentEvent.<String>builder()
.id(String.valueOf(seq))
.event(seq % 2 == 0 ? "even" : "odd")
.data("Count: " + counter.incrementAndGet())
.build());
}動(dòng)態(tài)推送特定用戶
使用 Map 存儲(chǔ)用戶連接:
private final Map<String, Sinks.Many<String>> userSinks = new ConcurrentHashMap<>();
@GetMapping("/sse/{userId}")
public Flux<ServerSentEvent<String>> userStream(@PathVariable String userId) {
Sinks.Many<String> sink = userSinks.computeIfAbsent(userId, k -> Sinks.many().multicast().onBackpressureBuffer());
return sink.asFlux().map(data -> ServerSentEvent.builder().data(data).build());
}異常處理
添加錯(cuò)誤重連邏輯:
return Flux.interval(Duration.ofSeconds(1))
.map(seq -> ServerSentEvent.<Integer>builder().data(counter.incrementAndGet()).build())
.onErrorResume(e -> Flux.just(ServerSentEvent.builder().data("Error: " + e.getMessage()).build()));5. 總結(jié)
Spring Boot 3.4.3 結(jié)合 Spring WebFlux 實(shí)現(xiàn) SSE 功能,為實(shí)時(shí)數(shù)據(jù)推送提供了優(yōu)雅的解決方案。通過本文的步驟,你可以快速搭建一個(gè)基于事件驅(qū)動(dòng)的后端服務(wù),滿足實(shí)時(shí)通知或監(jiān)控等需求。相比 WebSocket,SSE 更輕量且易于集成,適合單向推送場(chǎng)景。
到此這篇關(guān)于Spring Boot 3.4.3 基于 Spring WebFlux 實(shí)現(xiàn) SSE 功能的文章就介紹到這了,更多相關(guān)Spring Boot Spring WebFlux SSE內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot3中Spring?WebFlux?SSE服務(wù)器發(fā)送事件的實(shí)現(xiàn)步驟
- SpringBoot深入分析webmvc和webflux的區(qū)別
- springboot webflux 過濾器(使用RouterFunction實(shí)現(xiàn))
- SpringBoot之webflux全面解析
- Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例
- 詳解Spring Boot2 Webflux的全局異常處理
- 解決spring-boot2.0.6中webflux無法獲得請(qǐng)求IP的問題
相關(guān)文章
Springboot整合Dozer實(shí)現(xiàn)深度復(fù)制的方法
Dozer是一種Java?Bean到Java?Bean的映射器,遞歸地將數(shù)據(jù)從一個(gè)對(duì)象復(fù)制到另一個(gè)對(duì)象,它是一個(gè)強(qiáng)大的,通用的,靈活的,可重用的和可配置的開源映射框架,本文給大家介紹Springboot整合Dozer的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2022-03-03
SpringBoot項(xiàng)目整合Zookeeper常見錯(cuò)誤總結(jié)
本文總結(jié)了在使用Zookeeper和Dubbo進(jìn)行服務(wù)注冊(cè)與發(fā)現(xiàn)過程中遇到的常見問題及其解決方案,包括依賴配置錯(cuò)誤、配置文件錯(cuò)誤、啟動(dòng)失敗、運(yùn)行時(shí)常見錯(cuò)誤以及Zookeeper啟動(dòng)問題,并提供了一些最佳實(shí)踐建議,感興趣的朋友跟隨小編一起看看吧2026-01-01
IDEA編譯報(bào)錯(cuò)“java: 常量字符串過長(zhǎng)”的原因及解決方法
今天在開發(fā)過程中,由于嘗試將一個(gè)文件的 Base64 字符串設(shè)置為常量,結(jié)果導(dǎo)致 IDEA 編譯的時(shí)候出現(xiàn)了如下報(bào)錯(cuò)java: 常量字符串過長(zhǎng),所以本文給大家記錄了IDEA編譯報(bào)錯(cuò)“java: 常量字符串過長(zhǎng)”的原因及解決方法,需要的朋友可以參考下2025-02-02
org.slf4j.Logger中info()方法的使用詳解
這篇文章主要介紹了org.slf4j.Logger中info()方法的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java中十進(jìn)制字符串轉(zhuǎn)十六進(jìn)制的性能解讀

