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

相关推荐
Bolt14 小时前
用 pnpm 11 省掉项目里的 .nvmrc 与 .npmrc
前端·npm·node.js
猪猪聪明_V14 小时前
前端码农的本地项目启动器
前端·javascript
时光不负努力14 小时前
每天一个高级前端知识 - Day 21
前端
暗不需求14 小时前
前端性能优化 防抖与节流完全指南:从原理到最佳实践
前端·javascript·面试
@大迁世界14 小时前
45.什么是内联条件表达式(inline conditional expressions)?在事件处理里怎么用?
开发语言·前端·javascript·react.js·ecmascript
用户91868612868714 小时前
从物流查询聊策略模式:后端开发中的多策略设计
后端
一颗趴菜14 小时前
微信小程序如何去下载PDF呢
前端·javascript
bcbnb14 小时前
iOS开发中手动实现代码混淆的完整步骤与示例
后端·ios
KaMeidebaby14 小时前
卡梅德生物技术快报|细菌 FISH 实验 + 流式细胞术:尿路感染活菌快速定量系统实现与数据验证
前端·数据库·其他·百度·新浪微博
昆曲之源_娄江河畔14 小时前
DBGridEh Footer的使用
前端·数据库·delphi·dbgrideh