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 响应流本身

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

相关推荐
折哥的程序人生 · 物流技术专研3 小时前
Java面试85题图解版 · 特别篇:2026后端高频面试题复盘(算法底层逻辑+高并发架构设计全解析,附Java实战代码)
java·网络·数据库·算法·面试
xxie1237943 小时前
return与print
开发语言·python
秋93 小时前
从 Python 后端工程师转型 AI Engineer(AI 工程化)的完整补课清单(2026实战版)
开发语言·人工智能·python
一条泥憨鱼3 小时前
【Redis】数据类型和常用命令
java·数据库·redis·后端·缓存
云烟成雨TD3 小时前
Spring AI Alibaba 1.x 系列【78】沙箱(Sandbox)
java·人工智能·spring
程序员二叉3 小时前
【Java】 异常高频面试题精讲 | 易错点+对比总结
java·开发语言·面试
听你说324 小时前
科技护航极限征程 三诺生物助力雄关330长城越野赛
大数据·科技·健康医疗
周航宇JoeZhou4 小时前
JB3-9-SpringAI(二)
java·ai·agent·多智能体·调度·智能体·观察
好家伙VCC4 小时前
Web Components主题热切换方案揭秘
java·前端
慕木沐4 小时前
Google ADK Java 1.0版本 核心机制与实战 Demo
java·开发语言·python