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

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

相关推荐
Databend4 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
SamDeepThinking4 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
她的男孩7 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
荣码9 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
plainGeekDev10 小时前
Gson → kotlinx.serialization
android·java·kotlin
小bo波19 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
咖啡八杯20 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
阿里云大数据AI技术1 天前
StarRocks x Fluss x Paimon湖流一体方案:构建秒级响应、湖流一体的实时数据引擎
大数据·人工智能