1、pom文件
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
2、前端代码
<title> Springboot集成SSE title>
const clientId = new Date().getTime();
if (!!window.EventSource) {
source = new EventSource('http://127.0.0.1:8080/sse/subscribe?id=' + clientId);
source.onopen = function (event) {
setMessageInnerHTML("建立连接" + event);
source.onmessage = function (event) {
setMessageInnerHTML(event.data);
source.onerror = function (event) {
if (event.readyState === EventSource.CLOSED) {
setMessageInnerHTML("连接关闭");
setMessageInnerHTML("浏览器不支持SSE");
window.onbeforeunload = function () {
const httpRequest = new XMLHttpRequest();
httpRequest.open('GET', '/sse/over/?clientId=' + clientId, true);
function setMessageInnerHTML(innerHTML) {
document.getElementById('text').innerHTML += innerHTML + '
';
<button onclick="close()">关闭连接button>

3、后端代码
1、订阅
private static Map cache = new ConcurrentHashMap<>();
@GetMapping(path = "subscribe", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
public SseEmitter subscribe(@RequestParam(name = "id", required = false) String id) throws IOException {
SseEmitter sseEmitter = new SseEmitter(0L);
cache.put(id, sseEmitter);
sseEmitter.onCompletion(() -> {
sseEmitter.onError(throwable -> {
sseEmitter.onTimeout(() -> {
2、推送
@GetMapping(path = "push/{userId}")
public String push(@PathVariable String userId,@RequestBody Map param) throws IOException {
SseEmitter sseEmitter = cache.get(userId);
if (sseEmitter != null) {
sseEmitter.send(SseEmitter.event().name("msg").data("后端发送消息:" + param));
} catch (IOException e) {
log.error("用户[{}]推送异常:{}", userId, e.getMessage());
3、关闭
@GetMapping(path = "over")
public String over(@RequestParam(name = "id", required = false) String id) {
SseEmitter sseEmitter = cache.get(id);
if (sseEmitter != null) {