摘要:SSE更简单的单向数据传输(相对于websocket单向传输数据更简单),本文主要介绍SSE + SpringBoot的使用方式,SSE的原理不做详细的介绍,大家对协议原理有兴趣的,请百度其具体的原理。
简介
Server-Sent Events (SSE)是一种允许服务器主动向客户端浏览器发送数据的技术。它是基于 HTTP 协议的,允许服务器向客户端推送实时更新。通常用于只接收消息的场景,比如大屏实时更新最新的航班。
基本概念
- 事件流:服务器发送的事件序列。
- 重连:如果连接断开,客户端尝试重新连接服务器(浏览器会自动重连不需要代码控制)。
- Last-Event-ID:客户端接收到的最后一个事件的ID,可以用来从服务器请求缺失的事件。
案例
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
</dependencies>
SseController入口
@Slf4j
@RestController
@RequestMapping(value = "sse")
public class SseController {
private final CopyOnWriteArrayList<SseEmitter> emitters = new CopyOnWriteArrayList<>();
@GetMapping("/events")
public SseEmitter handleSse() {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
emitters.add(emitter);
emitter.onTimeout(() -> emitters.remove(emitter));
emitter.onCompletion(() -> emitters.remove(emitter));
return emitter;
}
@Scheduled(fixedDelay = 1000)
public void sendMessage(){
String message = JSON.toJSONString(ResponseMessage.success("当前时间:" + LocalDateTime.now()));
SseEmitter.SseEventBuilder eventBuilder = SseEmitter.event().id(System.currentTimeMillis() + "").data(message);
emitters.forEach(emitter -> {
try{
emitter.send(eventBuilder);
}catch (Exception ex){
log.error("发送异常", ex);
}
});
}
}
sse.html
前端测试入口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>sse</title>
</head>
<body>
<div id="data"></div>
<script>
var source = new EventSource('/sse/events');
source.onmessage = function(event) {
document.getElementById('data').innerHTML += event.data + '<br>';
};
</script>
</body>
</html>