使用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的核心实现,并根据实际需求扩展功能。建议根据具体场景选择合适的实时通信方案。

相关推荐
逸风尊者4 分钟前
开发需掌握的知识:MQTT协议
java·后端
Calm55019 分钟前
ele表单未输入值提示为英文
前端
老华带你飞26 分钟前
校务管理|基于springboot 校务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
JosieBook29 分钟前
【部署】Spring Boot + Vue框架项目生产环境部署完整方案
vue.js·spring boot·后端
油丶酸萝卜别吃30 分钟前
springboot项目中与接口文档有关的注解
java·spring boot·后端
爪洼守门员34 分钟前
前端性能优化
开发语言·前端·javascript·笔记·性能优化
Java爱好狂.39 分钟前
复杂知识简单学!Springboot加载配置文件源码分析
java·spring boot·后端·spring·java面试·后端开发·java程序员
TOYOAUTOMATON40 分钟前
GTH系列模组介绍
前端·目标检测·自动化
2022.11.7始学前端1 小时前
n8n第十节 把Markdown格式的会议纪要发到企微
前端·chrome·n8n
fruge1 小时前
Lodash 源码精读:防抖节流的实现细节与边界场景
前端