JAVA大数据场景使用StreamingOutput

JAX-RS StreamingOutput 详细讲解

一、StreamingOutput 是什么

StreamingOutput 不是"返回数据对象",而是"你亲手往 HTTP
响应流里写字节"。

它的接口定义:

java 复制代码
@FunctionalInterface
public interface StreamingOutput {
    void write(OutputStream output) throws IOException;
}

核心含义: - JAX-RS 不帮你序列化对象 - 不缓存完整结果 - 直接把 HTTP

Response 的 OutputStream 交给你


二、与普通返回方式的根本区别

普通返回

java 复制代码
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<User> getUsers() {
    return userService.findAll();
}

流程:

  • Java 对象
    → MessageBodyWriter
    → JSON
    → 一次性返回

特点: - 数据必须先完整生成 - 占用内存 - 适合小数据


StreamingOutput 返回

java 复制代码
@GET
@Produces("text/csv")
public StreamingOutput streamCsv() {
    return output -> {
        output.write("id,name\n".getBytes());
        output.write("1,Alice\n".getBytes());
    };
}

流程:

  • 客户端建立连接
    → 容器打开 OutputStream
    → 调用 write()
    → 边写边发送

特点: - 流式输出 - 几乎不占内存 - 适合大数据、下载


三、为什么说是在"写 HTTP 管道"

OutputStream 就是 TCP 连接上的 HTTP Response Body。

  • write():客户端立刻收到
  • flush():强制推送缓冲区
  • 异常:连接直接中断

你已经进入网络 IO 层。


四、典型使用场景

1. 大数据 CSV 导出

java 复制代码
@GET
@Produces("text/csv")
public StreamingOutput export() {
    return out -> {
        BufferedWriter writer = new BufferedWriter(
            new OutputStreamWriter(out, StandardCharsets.UTF_8)
        );
        writer.write("id,name\n");
        for (User u : userService.streamAll()) {
            writer.write(u.getId() + "," + u.getName() + "\n");
            writer.flush();
        }
    };
}

2. 长任务实时输出

java 复制代码
@GET
@Produces(MediaType.TEXT_PLAIN)
public StreamingOutput task() {
    return out -> {
        for (int i = 1; i <= 5; i++) {
            out.write(("step " + i + "\n").getBytes());
            out.flush();
            Thread.sleep(1000);
        }
    };
}

五、Response + StreamingOutput(推荐)

java 复制代码
@GET
public Response download() {
    StreamingOutput stream = out -> {
        out.write("hello".getBytes());
    };
    return Response.ok(stream)
            .header("Content-Disposition", "attachment; filename=test.txt")
            .build();
}

六、常见致命坑

1. 没有返回值概念

java 复制代码
return out -> {
    out.write(data);
};

2. 不要关闭 OutputStream

java 复制代码
out.close(); // ❌

3. write 后抛异常会导致下载损坏

4. 不会自动 JSON 序列化

java 复制代码
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, obj);

七、什么时候必须用 StreamingOutput

场景 是否使用
小 JSON
大文件下载
实时输出
普通 REST 查询

八、核心总结

StreamingOutput = 你控制 HTTP 响应流本身

不是返回数据,而是写网络字节。

相关推荐
cccccc语言我来了4 分钟前
【C++---unordered_set/map底层封装】个不拘一格的集合。它不似有序集合那般循规蹈矩,而是以一种洒脱不羁的方式,将元素们随意地散落其中。每一个元素都是独一无二的。
开发语言·c++·哈希算法
Zfox_4 分钟前
C++ IO流全解析:标准库中的数据处理与文件读写艺术
开发语言·c++
加号34 分钟前
【C#】实现沃德普线光控制器通信控制(附完整源码)
开发语言·c#
格鸰爱童话17 分钟前
向AI学习项目技能(五)
java·学习
程序员萌萌19 分钟前
Java之mysql实战讲解(三):聚簇索引与非聚簇索引
java·mysql·聚簇索引
天若有情67330 分钟前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
好家伙VCC34 分钟前
**发散创新:基于Python与ROS的机器人运动控制实战解析**在现代机器人系统开发中,**运动控制**是实现智能行为的核心
java·开发语言·python·机器人
2401_8274999934 分钟前
python项目实战09-AI智能伴侣(ai_partner_2-3)
开发语言·python
派葛穆36 分钟前
汇川PLC-Python与汇川easy521plc进行Modbustcp通讯
开发语言·python
程途知微1 小时前
ConcurrentHashMap线程安全实现原理全解析
java·后端