Spring SseEmitter 系统及作用详细讲解

 更新时间:2025年07月09日 10:04:25   作者:Code_Geo  
Spring SseEmitter基于HTTP的长连接,实现服务器单向推送数据,支持异步、多用户并发及超时管理,适用于实时通知、进度条等场景,相比WebSocket更轻量且易于实现,本文给大家介绍Spring SseEmitter系统及作用,感兴趣的朋友一起看看吧

SpringSseEmitter系统详细讲解

一、SSE 基本概念(Server-Sent Events)

  • SSE 是 HTML5 提出的标准。
  • 客户端通过 EventSource 向服务端发起 一个长连接,服务器通过该连接持续向客户端发送事件。
  • 相比 WebSocket(双向通信),SSE 是单向的:服务端 → 客户端
  • 本质上是基于 HTTP 协议的长连接

示例(前端代码)

const eventSource = new EventSource("/sse/subscribe");
eventSource.onmessage = function(event) {
    console.log("收到消息:", event.data);
};
eventSource.onerror = function(e) {
    console.error("连接错误", e);
};

二、Spring 的SseEmitter作用

Spring 提供了 SseEmitter 类来简化 SSE 的开发,它本质上是一个 Controller 的返回对象,用于不断地往前端推送数据。

三、基本用法

1. 添加依赖(Spring Boot Web 项目一般已包含)

<!-- Maven 中无需额外添加,spring-boot-starter-web 已包含 -->

2. 控制器定义 SSE 接口

@RestController
public class SseController {
    @GetMapping("/sse/subscribe")
    public SseEmitter subscribe() {
        SseEmitter emitter = new SseEmitter(0L); // 不超时,或设置时间,如30_000L
        Executors.newSingleThreadExecutor().submit(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    emitter.send("第 " + i + " 条消息");
                    Thread.sleep(1000);
                }
                emitter.complete(); // 关闭连接
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });
        return emitter;
    }
}

四、SseEmitter 的重要方法

方法说明
send(Object data)向客户端发送消息,支持字符串、JSON 等
send(Object data, MediaType mediaType)指定 MIME 类型发送
complete()正常关闭连接
completeWithError(Throwable ex)异常关闭连接
onCompletion(Runnable callback)设置连接关闭的回调
onTimeout(Runnable callback)设置超时回调
onError(Consumer<Throwable> callback)设置错误回调
setTimeout(long timeout)设置连接超时时间(默认 30 秒)

五、注意事项

1. Content-Type

Content-Type: text/event-stream

Spring 会自动设置,只需:

@GetMapping(value = "/sse/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)

2. 浏览器自动重连机制

  • 如果服务端关闭连接(未调用 .complete()),浏览器会默认自动尝试重新连接。
  • 禁止客户端重连可发送 retry: 0

3. 多用户支持

private final Map<String, SseEmitter> userEmitters = new ConcurrentHashMap<>();
@GetMapping("/subscribe/{userId}")
public SseEmitter subscribe(@PathVariable String userId) {
    SseEmitter emitter = new SseEmitter(60_000L);
    userEmitters.put(userId, emitter);
    emitter.onCompletion(() -> userEmitters.remove(userId));
    emitter.onTimeout(() -> userEmitters.remove(userId));
    return emitter;
}
public void sendToUser(String userId, String message) throws IOException {
    SseEmitter emitter = userEmitters.get(userId);
    if (emitter != null) {
        emitter.send(message);
    }
}

六、典型应用场景

  • 实时进度条
  • 实时通知系统
  • 日志推送
  • 后台任务结果反馈

七、SseEmitter 与 WebSocket 的对比

比较项SSE(SseEmitter)WebSocket
通信方向单向(服务端 → 客户端)双向
协议HTTPws:// 或 wss://
浏览器支持广泛支持广泛支持
实现复杂度简单需要管理连接
使用场景实时推送聊天、游戏等

八、SseEmitter 高级技巧

✅ 自定义事件名称

emitter.send(SseEmitter.event()
    .name("customEvent")
    .data("这是自定义事件")
);

前端监听:

eventSource.addEventListener("customEvent", function(event) {
    console.log("收到自定义事件:", event.data);
});

✅ 定时心跳保持连接

ScheduledExecutorService heartbeatScheduler = Executors.newScheduledThreadPool(1);
heartbeatScheduler.scheduleAtFixedRate(() -> {
    try {
        emitter.send("heartbeat");
    } catch (IOException e) {
        emitter.completeWithError(e);
    }
}, 0, 15, TimeUnit.SECONDS);

九、总结

特性支持情况
异步发送
多用户并发
超时与关闭管理
自定义事件类型
应用场景实时推送、轻量通知

到此这篇关于Spring SseEmitter 系统详细讲解的文章就介绍到这了,更多相关Spring SseEmitter 系统内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot处理跨域请求(CORS)的五种方式

    SpringBoot处理跨域请求(CORS)的五种方式

    跨域资源共享(CORS)是现代Web开发中常见的问题,Spring Boot提供了多种方式来处理CORS请求,下面我将详细介绍各种实现方式及其适用场景,需要的朋友可以参考下
    2025-04-04
  • java基础之Object类

    java基础之Object类

    这篇文章主要介绍了java基础之Object类 的相关资料,需要的朋友可以参考下
    2015-06-06
  • 使用ObjectMapper解析json不用一直new了

    使用ObjectMapper解析json不用一直new了

    这篇文章主要为大家介绍了使用ObjectMapper解析json不用一直new了的方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Eclipse运行android项目报错Unable to build: the file dx.jar was not loaded from the SDK folder的解决办法

    Eclipse运行android项目报错Unable to build: the file dx.jar was not

    今天小编就为大家分享一篇关于Eclipse运行android项目报错Unable to build: the file dx.jar was not loaded from the SDK folder的解决办法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java Socket编程心跳包创建实例解析

    Java Socket编程心跳包创建实例解析

    这篇文章主要介绍了Java Socket编程心跳包创建实例解析,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • JAVA操作MongoDB数据库实例教程

    JAVA操作MongoDB数据库实例教程

    MongoDB是一个文档型数据库,是NOSQL家族中最重要的成员之一,下面这篇文章主要给大家介绍了关于JAVA操作MongoDB数据库的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • java中的多态和继承示例分析

    java中的多态和继承示例分析

    这篇文章主要介绍了java中的多态和继承,结合实例形式分析了java中的多态和继承原理、实现方法及相关操作注意事项,需要的朋友可以参考下
    2020-05-05
  • Servlet实现简单文件上传功能

    Servlet实现简单文件上传功能

    这篇文章主要为大家详细介绍了Servlet实现简单文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Java使用flyway实现脚本自动化的方法详解

    Java使用flyway实现脚本自动化的方法详解

    Flyway是一个开源的数据库版本控制工具,主要用于管理数据库的版本和变更,它可以自动化地将数据库迁移到不同的版本,同时支持多种数据库类型,本文给大家介绍了如何使用flyway实现脚本自动化,需要的朋友可以参考下
    2023-10-10
  • 使用Spring Boot快速构建一个简单的文件处理工具

    使用Spring Boot快速构建一个简单的文件处理工具

    在现代Web应用中,文件上传与处理是常见的需求,本文将通过一个实际案例,详细介绍如何使用Spring Boot构建一个文件处理工具,感兴趣的小伙伴可以参考一下
    2025-06-06

最新评论