Spring Boot 整合 SSE(Server-Sent Events)

1、简述

SSE(Server-Sent Events)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实时更新。与WebSocket不同,SSE更简单,使用HTTP/1.1协议即可,不需要额外的协议升级。

SSE的特点:

  • 单向通信:服务器推送数据给客户端,客户端无法向服务器发送消息。

  • 简单易用:基于HTTP协议,无需复杂的配置。

  • 浏览器支持:现代浏览器大多内置支持(如Chrome、Edge、Firefox等)。

2、Spring Boot 中的SSE实现

2.1 添加依赖

SSE无需额外的依赖,Spring Boot自带对SSE的支持。创建一个Spring Boot项目即可。

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.2 实现后端接口

使用MediaType.TEXT_EVENT_STREAM_VALUE作为返回类型即可开启SSE。以下代码是一个简单的实现。

java 复制代码
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() {
        // 模拟数据流
        return Stream.generate(() -> "当前时间:" + LocalTime.now())
                     .limit(10); // 限制10条消息
    }
}

2.3 配置超时时间(可选)

默认情况下,Spring Boot的响应会超时。可以在application.properties中调整超时时间:

java 复制代码
server.servlet.session.timeout=30s
spring.mvc.async.request-timeout=30000

2.4 前端实现

SSE在前端通过EventSource对象实现。以下是一个简单的前端示例:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SSE Example</title>
</head>
<body>
    <h1>实时消息</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连接出错,正在尝试重连...');
            eventSource.close();
        };
    </script>
</body>
</html>

3、高级实践

使用Spring Scheduler推送数据,在实际场景中,可能需要定时向客户端推送数据。例如,监控系统定时更新。

java 复制代码
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);
            }
        }
    }
}

创建一个控制器订阅和推送消息:

java 复制代码
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("当前时间:" + System.currentTimeMillis());
    }
}

注意事项:

  • 浏览器兼容性:SSE不支持IE,但现代浏览器支持良好。

  • 连接断开处理:可通过EventSourceonerror事件重新连接。

  • 性能问题:对大量订阅者时,需考虑使用分布式消息队列优化(如Kafka)。

  • 超时时间:默认30秒超时,需要根据实际需求调整。

4、适用场景

  • 实时通知:如监控系统的告警推送。

  • 实时更新:如股票行情、体育比分。

  • 消息流:如系统日志、任务进度。

相关推荐
喻米粒06221 小时前
RabbitMQ消息相关
java·jvm·spring boot·spring·spring cloud·sentinel·java-rabbitmq
清风絮柳6 小时前
51. “闲转易”交易平台小程序(基于springboot&vue)
vue.js·spring boot·小程序·毕业设计·校园二手交易平台·二手交易小程序·闲转易交易系统
TheITSea7 小时前
后端开发 SpringBoot 工程模板
spring boot·后端
Micro麦可乐8 小时前
最新Spring Security实战教程(七)方法级安全控制@PreAuthorize注解的灵活运用
java·spring boot·后端·spring·intellij-idea·spring security
教练 我想学编程8 小时前
学习记录706@微信小程序+springboot项目 真机测试 WebSocket错误: {errMsg: Invalid HTTP status.}连接不上
spring boot·学习·微信小程序
_Djhhh9 小时前
基于SpringAOP面向切面编程的一些实践(日志记录、权限控制、统一异常处理)
java·spring boot·spring·maven·sprint
小杨40410 小时前
springboot框架项目实践应用十四(扩展sentinel错误提示)
spring boot·后端·spring cloud
冬天豆腐12 小时前
Springboot集成Dubbo和Zookeeper框架搭建
spring boot·dubbo·java-zookeeper
风象南12 小时前
Spring Boot 实现文件秒传功能
java·spring boot·后端
橘猫云计算机设计12 小时前
基于django优秀少儿图书推荐网(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·小程序·django·毕业设计