Spring Boot 整合 SSE的高級(jí)實(shí)踐(Server-Sent Events)
1、簡(jiǎn)述
SSE(Server-Sent Events)是一種基于HTTP協(xié)議的單向通信機(jī)制,允許服務(wù)器向?yàn)g覽器持續(xù)發(fā)送實(shí)時(shí)更新。與WebSocket不同,SSE更簡(jiǎn)單,使用HTTP/1.1協(xié)議即可,不需要額外的協(xié)議升級(jí)。
SSE的特點(diǎn):
- 單向通信:服務(wù)器推送數(shù)據(jù)給客戶端,客戶端無法向服務(wù)器發(fā)送消息。
- 簡(jiǎn)單易用:基于HTTP協(xié)議,無需復(fù)雜的配置。
- 瀏覽器支持:現(xiàn)代瀏覽器大多內(nèi)置支持(如Chrome、Edge、Firefox等)。
2、Spring Boot 中的SSE實(shí)現(xiàn)
2.1 添加依賴
SSE無需額外的依賴,Spring Boot自帶對(duì)SSE的支持。創(chuàng)建一個(gè)Spring Boot項(xiàng)目即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>2.2 實(shí)現(xiàn)后端接口
使用MediaType.TEXT_EVENT_STREAM_VALUE作為返回類型即可開啟SSE。以下代碼是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)。
package com.example.sse.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@RestController
public class SseController {
@GetMapping(value = "/sse/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Stream<String> stream() {
// 模擬數(shù)據(jù)流
return Stream.generate(() -> "當(dāng)前時(shí)間:" + LocalTime.now())
.limit(10); // 限制10條消息
}
}2.3 配置超時(shí)時(shí)間(可選)
默認(rèn)情況下,Spring Boot的響應(yīng)會(huì)超時(shí)??梢栽?code>application.properties中調(diào)整超時(shí)時(shí)間:
server.servlet.session.timeout=30s spring.mvc.async.request-timeout=30000
2.4 前端實(shí)現(xiàn)
SSE在前端通過EventSource對(duì)象實(shí)現(xiàn)。以下是一個(gè)簡(jiǎn)單的前端示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSE Example</title>
</head>
<body>
<h1>實(shí)時(shí)消息</h1>
<div id="messages"></div>
<script>
const eventSource = new EventSource('/sse/stream');
eventSource.onmessage = function(event) {
const messagesDiv = document.getElementById('messages');
const newMessage = document.createElement('p');
newMessage.textContent = event.data;
messagesDiv.appendChild(newMessage);
};
eventSource.onerror = function() {
console.error('SSE連接出錯(cuò),正在嘗試重連...');
eventSource.close();
};
</script>
</body>
</html>3、高級(jí)實(shí)踐
使用Spring Scheduler推送數(shù)據(jù),在實(shí)際場(chǎng)景中,可能需要定時(shí)向客戶端推送數(shù)據(jù)。例如,監(jiān)控系統(tǒng)定時(shí)更新。
package com.example.sse.service;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
@Service
public class SsePushService {
private final CopyOnWriteArrayList<SseEmitter> emitters = new CopyOnWriteArrayList<>();
public SseEmitter subscribe() {
SseEmitter emitter = new SseEmitter(30_000L);
emitters.add(emitter);
emitter.onCompletion(() -> emitters.remove(emitter));
emitter.onTimeout(() -> emitters.remove(emitter));
return emitter;
}
public void pushMessage(String message) {
for (SseEmitter emitter : emitters) {
try {
emitter.send(message, MediaType.TEXT_PLAIN);
} catch (IOException e) {
emitters.remove(emitter);
}
}
}
}創(chuàng)建一個(gè)控制器訂閱和推送消息:
package com.example.sse.controller;
import com.example.sse.service.SsePushService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SsePushController {
private final SsePushService ssePushService;
public SsePushController(SsePushService ssePushService) {
this.ssePushService = ssePushService;
}
@GetMapping("/sse/subscribe")
public SseEmitter subscribe() {
return ssePushService.subscribe();
}
@GetMapping("/sse/push")
public void pushMessage() {
ssePushService.pushMessage("當(dāng)前時(shí)間:" + System.currentTimeMillis());
}
}注意事項(xiàng):
- 瀏覽器兼容性:SSE不支持IE,但現(xiàn)代瀏覽器支持良好。
- 連接斷開處理:可通過
EventSource的onerror事件重新連接。 - 性能問題:對(duì)大量訂閱者時(shí),需考慮使用分布式消息隊(duì)列優(yōu)化(如Kafka)。
- 超時(shí)時(shí)間:默認(rèn)30秒超時(shí),需要根據(jù)實(shí)際需求調(diào)整。
4、適用場(chǎng)景
- 實(shí)時(shí)通知:如監(jiān)控系統(tǒng)的告警推送。
- 實(shí)時(shí)更新:如股票行情、體育比分。
- 消息流:如系統(tǒng)日志、任務(wù)進(jìn)度。
到此這篇關(guān)于Spring Boot 整合 SSE(Server-Sent Events)的文章就介紹到這了,更多相關(guān)Spring Boot 整合 SSE內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?AI借助全局參數(shù)實(shí)現(xiàn)智能數(shù)據(jù)庫操作與個(gè)性化待辦管理
這篇文章主要介紹了Spring?AI借助全局參數(shù)實(shí)現(xiàn)智能數(shù)據(jù)庫操作與個(gè)性化待辦管理,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-11-11
SpringBoot處理請(qǐng)求參數(shù)中包含特殊符號(hào)
今天寫代碼遇到了一個(gè)問題,請(qǐng)求參數(shù)是個(gè)路徑“D:/ExcelFile”,本文就詳細(xì)的介紹一下該錯(cuò)誤的解決方法,感興趣的可以了解一下2021-06-06
使用dom4j實(shí)現(xiàn)xml轉(zhuǎn)map與xml轉(zhuǎn)json字符串
這篇文章主要為大家詳細(xì)介紹了如何使用dom4j實(shí)現(xiàn)xml轉(zhuǎn)map與xml轉(zhuǎn)json字符串功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-11-11
java遍歷http請(qǐng)求request的所有參數(shù)實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava遍歷http請(qǐng)求request的所有參數(shù)實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
Java客戶端服務(wù)端上傳接收文件實(shí)現(xiàn)詳解
這篇文章主要介紹了Java客戶端服務(wù)端上傳接收文件實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
如何把idea中的項(xiàng)目導(dǎo)入github倉庫中(圖文詳解)
這篇文章主要介紹了如何把idea中的項(xiàng)目導(dǎo)入github倉庫中,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Java仿文庫的基本方法(openoffice+swftools+flexPaper)
這篇文章主要為大家詳細(xì)介紹了Java仿文庫的基本方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Java版本怎么選以及JDK各版本特性對(duì)比與實(shí)戰(zhàn)建議
Java是一種廣泛使用的編程語言,擁有一個(gè)龐大的社區(qū)和大量的生態(tài)系統(tǒng),自從Java的早期版本以來,它已經(jīng)經(jīng)歷了許多變化和改進(jìn),這篇文章主要介紹了Java版本怎么選以及JDK各版本特性對(duì)比與實(shí)戰(zhàn)建議的相關(guān)資料,需要的朋友可以參考下2025-11-11

