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

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

相关推荐
2的n次方_1 分钟前
CANN Ascend C 编程语言深度解析:异构并行架构、显式存储层级与指令级精细化控制机制
c语言·开发语言·架构
亓才孓1 分钟前
[JDBC]PreparedStatement替代Statement
java·数据库
永霖光电_UVLED23 分钟前
打造更优异的 UVB 激光器
大数据·制造·量子计算
_F_y24 分钟前
C++重点知识总结
java·jvm·c++
打工的小王25 分钟前
Spring Boot(三)Spring Boot整合SpringMVC
java·spring boot·后端
毕设源码-赖学姐27 分钟前
【开题答辩全过程】以 高校体育场馆管理系统为例,包含答辩的问题和答案
java·spring boot
我真会写代码28 分钟前
SSM(指南一)---Maven项目管理从入门到精通|高质量实操指南
java·spring·tomcat·maven·ssm
m0_4665252928 分钟前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
vx_Biye_Design29 分钟前
【关注可免费领取源码】房屋出租系统的设计与实现--毕设附源码40805
java·spring boot·spring·spring cloud·servlet·eclipse·课程设计
java干货33 分钟前
为什么 “File 10“ 排在 “File 2“ 前面?解决文件名排序的终极算法:自然排序
开发语言·python·算法