Java中ResponseBodyEmitter的实现

 更新时间:2025年04月01日 16:34:15   作者:码力无边-OEC  
这篇文章主要介绍了Java中ResponseBodyEmitter的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

在开发高并发应用或处理长时间任务时,服务端需要向客户端实时推送数据,而不是一次性将所有结果返回。Spring 提供了一种优雅的解决方案:ResponseBodyEmitter。它适用于需要逐步发送响应数据的场景,比如进度条更新、实时日志输出、消息流等。本文将深入讲解 ResponseBodyEmitter 的核心概念、使用场景、完整示例以及注意事项,帮助初学者快速掌握其使用方法。

什么是 ResponseBodyEmitter?

ResponseBodyEmitter 是 Spring MVC 提供的一个类,用于实现服务端向客户端分块推送响应数据。它是异步非阻塞的,可以在响应未完成时多次向客户端发送部分数据,而无需等待任务完成。

特性

  • 异步非阻塞:支持异步任务,可以有效提高服务端吞吐量。
  • 实时性:能够逐步将数据推送给客户端,适用于实时数据更新场景。
  • 兼容性:基于标准的 HTTP 协议,客户端无需特殊支持。

ResponseBodyEmitter 的基本用法

核心方法

  • send(Object data):向客户端发送数据,可以多次调用。
  • complete():结束响应流,表示数据发送完毕。
  • onTimeout(Runnable callback):设置超时回调函数。
  • onCompletion(Runnable callback):设置完成回调函数。

典型使用场景

  • 实时日志输出:将长时间运行任务的日志实时返回给客户端。
  • 进度条更新:在任务执行过程中动态更新任务进度。
  • 数据流式加载:用于大数据分片加载,比如分页查询实时返回结果。

实战:实现一个实时推送的示例

下面我们通过一个完整的例子,演示如何使用 ResponseBodyEmitter 实现任务进度实时推送功能。

示例代码

1. 创建 Controller

@RestController
@RequestMapping("/api/progress")
public class ProgressController {

    @GetMapping("/start")
    public ResponseBodyEmitter startTask() {
        // 创建一个 ResponseBodyEmitter 实例
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();

        // 模拟一个耗时任务
        new Thread(() -> {
            try {
                for (int i = 1; i <= 100; i += 10) {
                    // 向客户端发送进度
                    emitter.send("Progress: " + i + "%\n");
                    Thread.sleep(1000); // 模拟任务耗时
                }
                emitter.complete(); // 任务完成,关闭连接
            } catch (Exception e) {
                emitter.completeWithError(e); // 出现异常时通知客户端
            }
        }).start();

        return emitter; // 返回 Emitter
    }
}

2. 测试接口

可以使用 Postman、浏览器或客户端代码调用接口:
URLhttp://localhost:8080/api/progress/start

客户端会逐步接收到如下响应:

Progress: 10%
Progress: 20%
Progress: 30%
...
Progress: 100%

深入分析

ResponseBodyEmitter 工作原理

  • 服务端异步生成响应数据:任务执行时,调用 send() 方法将数据推送至客户端。
  • 分块传输:数据以 HTTP 的**分块编码(Chunked Encoding)**方式传输,不会提前设置 Content-Length,而是分段发送数据块。
  • 连接生命周期:通过 complete() 或 completeWithError() 控制连接的关闭。

重要注意事项

  • 支持的客户端:大多数浏览器和 HTTP 客户端库支持分块传输,但某些老旧的客户端可能不支持。
  • 超时设置:为了避免长连接占用资源,可以为 ResponseBodyEmitter 设置超时时间:
    emitter.onTimeout(() -> emitter.complete());
    
  • 线程安全ResponseBodyEmitter 的 send() 方法是线程安全的,但需要注意控制任务线程的生命周期。
  • 连接关闭:需要确保任务结束时调用 complete() 或 completeWithError(),否则可能导致资源泄露。

扩展:与 Streaming 和 SSE 的对比

  • Streaming:直接通过 OutputStream 向客户端写入数据,灵活性高,但需手动处理流的关闭。
  • Server-Sent Events (SSE):基于 text/event-stream,适用于服务端事件推送,客户端需支持 SSE。
  • ResponseBodyEmitter:更通用,适用于任何支持 HTTP 的客户端,且易于与 Spring 集成。

总结

ResponseBodyEmitter 是 Spring 提供的轻量级流式传输解决方案,能有效提升高并发和实时性场景的用户体验。通过本文的讲解和示例,相信大家已经掌握了它的使用技巧和注意事项。在实际项目中,不妨尝试将其应用于实时日志、进度更新等场景,让你的应用更加智能、高效。

到此这篇关于Java中ResponseBodyEmitter的实现的文章就介绍到这了,更多相关Java ResponseBodyEmitter内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot读取properties配置文件中的数据的三种方法

    SpringBoot读取properties配置文件中的数据的三种方法

    本文主要介绍了SpringBoot读取properties配置文件中的数据的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Gateway网关源码解析

    Gateway网关源码解析

    这篇文章主要介绍了Gateway微服务网关,负载均衡,熔断和限流,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • Feign接口方法返回值设置方式

    Feign接口方法返回值设置方式

    这篇文章主要介绍了Feign接口方法返回值设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java实现上传网络图片到微信临时素材

    java实现上传网络图片到微信临时素材

    这篇文章主要为大家详细介绍了java实现上传网络图片到微信临时素材,网络图片上传到微信服务器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Java中字符串替换的4种方法代码举例

    Java中字符串替换的4种方法代码举例

    这篇文章主要介绍了Java中四种字符串替换方法,分别是String.replace()、String.replaceAll()、String.replaceFirst()和StringBuilder.replace(),并对比了它们的特点和适用场景,需要的朋友可以参考下
    2025-02-02
  • JVM性能调优实战:让你的IntelliJ Idea纵享丝滑

    JVM性能调优实战:让你的IntelliJ Idea纵享丝滑

    这篇文章主要介绍了JVM性能调优实战:让你的IntelliJ Idea纵享丝滑的相关资料,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • IDEA-Maven项目的jdk版本设置方法

    IDEA-Maven项目的jdk版本设置方法

    我们需要设置jdk的版本,不然会提示导致语法错误,这篇文章主要介绍了IDEA-Maven项目的jdk版本设置方法,小编觉得不错,一起来了解一下
    2019-04-04
  • Java SpringBoot使用guava过滤器

    Java SpringBoot使用guava过滤器

    这篇文章主要介绍了Java SpringBoot使用guava过滤器,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • 用java实现扫雷游戏

    用java实现扫雷游戏

    这篇文章主要为大家详细介绍了用java实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 详解java 客户端链接不上redis解决方案

    详解java 客户端链接不上redis解决方案

    这篇文章主要介绍了详解java 客户端链接不上redis解决方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01

最新评论