单一源事件(SSE)的一个spring boot实现,常用来将服务端内容实时推送到前端展示
[!前言]
不同于WebSockets提供了双向通信的能力,SSE只支持单向通信。但对于一些场景,如服务器向客户端发送通知或实时更新,SSE是一个简单且有效的选择。
说明
单一源事件(SSE)是一种用于实现服务器向客户端推送数据的网络技术。通常Web应用程序是基于请求-响应模式工作的,客户端需要定期向服务器发送请求以获取更新的数据。但是对于需要实时更新的应用,如聊天应用、股票市场更新等,这种轮询的方式效率不高。
SSE技术通过建立一次持久的连接,允许服务器主动向客户端发送数据,而不需要客户端发送请求。这种推送模式能够显著减少网络流量和服务器负载,同时实现实时更新。在SSE中,服务器向客户端发送一系列数据块,每个数据块以"event: "、"data: "和两个换行符开始,并以一个空行结束。客户端通过监听服务器发送的数据块来获取更新。
后端实现
以下模拟一个接口请求将每秒饭返回一条数据,持续十秒
package cn.allbs.sse.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 类 SSEController
* * @author ChenQi
* @date 2024/5/6
*/@RestController
public class SSEController {
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
@GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter receiveText(@RequestParam String question) {
SseEmitter emitter = new SseEmitter();
executorService.execute(() -> {
try {
// 处理接收到的文本内容
String processedText = processText(question);
// 将处理结果逐步发送给客户端
for (int i = 1; i <= 10; i++) {
emitter.send(processedText.replace("问题", "回答") + i);
Thread.sleep(1000); // 模拟每秒发送一个字符
}
emitter.complete(); // 发送完毕,关闭连接
} catch (Exception e) {
emitter.completeWithError(e); // 发生错误,关闭连接
}
});
return emitter;
}
// 在实际应用中,这里可以添加对文本内容的具体处理逻辑
private String processText(String text) {
return "这是问题:" + text;
}
}
前端界面可以随意一点画下即可
<!DOCTYPE html>
<html>
<head>
<title>SSE Demo</title>
<meta charset="utf-8">
<script type="text/javascript">
var eventSource;
function stopSSE() {
if (eventSource) {
eventSource.close();
}
}
function sendText() {
var inputField = document.getElementById("input-field");
var text = inputField.value.trim();
if (text !== "") {
eventSource = new EventSource("/events?question=" + text);
eventSource.onmessage = function(event) {
var textField = document.getElementById("result-field");
textField.value += (event.data + ", ");
};
eventSource.onerror = function(event) {
console.error("EventSource failed:", event);
eventSource.close();
};
}
}
</script>
</head>
<body>
<input type="text" id="input-field" placeholder="输入内容">
<button onclick="sendText()">发送</button><br><br>
<textarea id="result-field" rows="10" cols="50" readonly></textarea><br><br>
<button onclick="stopSSE()">Stop SSE</button>
</body>
</html>
访问页面
http://{ip}:{port}/index.html
实现效果
demo地址
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ALLBS!
评论