使用Spring Boot实现Server-Sent Events(SSE)实时推送

使用Spring Boot实现Server-Sent Events(SSE)实时推送

什么是SSE?

Server-Sent Events(SSE) 是一种基于HTTP的服务器向客户端单向实时推送数据的技术。与WebSocket不同,SSE仅支持服务器到客户端的单向通信,适用于实时通知、股票行情、新闻推送等场景。

核心特性:

  • 基于HTTP协议,兼容现有基础设施
  • 支持自动重连
  • 轻量级,使用简单
  • 默认支持文本数据格式

一、快速搭建Spring Boot SSE服务

1. 创建项目

通过Spring Initializr创建项目,选择依赖:

  • Spring Web(用于Web端点)

2. 实现SSE控制器

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

@RestController
public class SSEController {

    private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    // 客户端连接端点
    @GetMapping(path = "/connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter connect(@RequestParam String userId) {
        SseEmitter emitter = new SseEmitter(60_000L); // 超时时间60秒
        
        // 注册清理回调
        emitter.onCompletion(() -> emitters.remove(userId));
        emitter.onTimeout(() -> emitters.remove(userId));
        
        emitters.put(userId, emitter);
        return emitter;
    }

    // 消息推送方法(可在Service中调用)
    public void sendEvent(String userId, String message) {
        SseEmitter emitter = emitters.get(userId);
        if (emitter != null) {
            try {
                emitter.send(SseEmitter.event()
                        .data(message)
                        .name("custom-event")); // 自定义事件名称
            } catch (IOException e) {
                emitters.remove(userId);
            }
        }
    }
}

二、客户端实现

HTML页面示例:

html 复制代码
<!DOCTYPE html>
<html>
<body>
    <div id="messages"></div>
    <script>
        const eventSource = new EventSource('http://localhost:8080/connect?userId=123');
        
        // 监听默认消息
        eventSource.onmessage = (e) => {
            document.getElementById('messages').innerHTML += e.data + '<br>';
        };

        // 监听自定义事件
        eventSource.addEventListener('custom-event', (e) => {
            console.log('Custom event:', e.data);
        });
    </script>
</body>
</html>

三、进阶功能实现

1. 广播消息

java 复制代码
public void broadcast(String message) {
    emitters.forEach((id, emitter) -> {
        try {
            emitter.send(message);
        } catch (IOException e) {
            emitters.remove(id);
        }
    });
}

2. 发送结构化数据(JSON)

java 复制代码
emitter.send(SseEmitter.event()
        .data(new MyDataObject("value"), MediaType.APPLICATION_JSON)
        .id("event-123")
        .reconnectTime(5000));

3. 心跳机制(防止连接超时)

java 复制代码
@Scheduled(fixedRate = 30_000)
public void sendHeartbeat() {
    emitters.forEach((id, emitter) -> {
        try {
            emitter.send(SseEmitter.event().comment("heartbeat"));
        } catch (IOException ignored) {}
    });
}

四、注意事项

  1. 连接管理

    • 使用ConcurrentHashMap存储连接
    • 及时移除已关闭的连接
    • 设置合理的超时时间(默认:30秒)
  2. 跨域问题

    java 复制代码
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/connect")
                    .allowedOrigins("*");
        }
    }
  3. 性能优化

    • 调整Tomcat线程池配置
    • 考虑使用异步处理(@Async

五、SSE vs WebSocket

特性 SSE WebSocket
协议 HTTP WS/TCP
通信方向 单向(服务器→客户端) 双向
数据格式 Text/Event-Stream 二进制/自定义
自动重连 支持 需手动实现
浏览器兼容性 除IE外主流浏览器 现代浏览器

总结

SSE是实现服务器推送的高效解决方案,适用于需要实时更新但不需要双向通信的场景。结合Spring Boot的SseEmitter,开发者可以快速构建实时功能。完整示例代码已上传至GitHub仓库

扩展阅读:


通过本文,读者可以快速掌握SSE的核心实现,并根据实际需求扩展功能。建议根据具体场景选择合适的实时通信方案。

相关推荐
步行cgn19 分钟前
在 HTML 表单中,name 和 value 属性在 GET 和 POST 请求中的对应关系如下:
前端·hive·html
hrrrrb26 分钟前
【Java Web 快速入门】十一、Spring Boot 原理
java·前端·spring boot
找不到工作的菜鸟35 分钟前
Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
前端·javascript·html
Java微观世界37 分钟前
Object核心类深度剖析
java·后端
定栓37 分钟前
vue3入门-v-model、ref和reactive讲解
前端·javascript·vue.js
MrSYJ41 分钟前
为什么HttpSecurity会初始化创建两次
java·后端·程序员
专注API从业者42 分钟前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink
龙在天43 分钟前
H5开发,开发照相机,以及组件封装
前端
曼妥思1 小时前
PosterKit:跨框架海报生成工具
前端·开源
用户4822137167751 小时前
C++——类和对象
后端