StreamingResponseBody:处理大批量数据导出

StreamingResponseBody 简介

Spring框架中,StreamingResponseBody 是一个接口,它允许我们以流的方式写入HTTP响应体。这种方式非常适合处理大文件下载、大批量数据导出等场景,因为它可以避免一次性加载所有数据到内存中,从而减少内存占用并提高性能。

使用 StreamingResponseBody 的主要优势包括

  • 流式传输:数据可以分块地发送给客户端,而不是等待整个文件准备完毕。

  • 低内存占用:只在需要时加载数据,并立即发送给客户端,减少了对服务器内存的压力。

  • 更好的用户体验:用户无需长时间等待,文件开始生成后即可逐步接收到内容。

我们将采用StreamingResponseBody来实现流式响应,同时结合分页查询和异步处理。以下是带有详细注释的优化实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@RestController
@RequestMapping("/orders")
public class OptimizedOrderController {
    @Autowired
    private OrderService orderService;
    /**
     * 处理订单导出请求,使用StreamingResponseBody实现流式响应。
     * 这样做可以确保即使有大量的订单数据也不会导致内存溢出,
     * 同时可以让用户更快地开始接收文件。
     */
    @GetMapping("/export")
    public ResponseEntity<StreamingResponseBody> exportOrders() {
        // 创建StreamingResponseBody实例,该对象将在每次有新数据可写时被调用
        StreamingResponseBody stream = outputStream -> {
            int pageSize = 1000; // 每页查询的数量
            int pageNumber = 0;  // 分页起始页码
            boolean hasMoreData = true; // 是否还有更多数据标志
            try {
                // 循环直到所有数据都被处理完毕
                while (hasMoreData) {
                    // 构造分页请求参数
                    PageRequest pageRequest = PageRequest.of(pageNumber++, pageSize, Sort.by("id"));
                    // 执行分页查询
                    Page<Order> page = orderService.findPage(pageRequest);
                    // 遍历当前页的数据,并逐行写入输出流
                    for (Order order : page.getContent()) {
                        writeOrderToExcelRow(order, outputStream);
                    }
                    // 更新是否有更多数据的标志
                    hasMoreData = page.hasNext();
                }
            } catch (IOException e) {
                // 如果发生IO异常,记录日志或采取其他措施
                e.printStackTrace();
            }
        };
        // 设置HTTP头信息,告知浏览器这是一个附件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=orders.xlsx");
        // 返回包含StreamingResponseBody的ResponseEntity对象
        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_OCTET_STREAM) // 设置响应的内容类型为二进制流
                .body(stream); // 将StreamingResponseBody作为响应体
    }
    /**
     * 将单个订单转换成一行Excel格式,并写入到提供的输出流中。
     * 注意:这里简化了实际的Excel写入逻辑,具体实现依赖于所使用的库(如Apache POI)。
     */
    private void writeOrderToExcelRow(Order order, OutputStream outputStream) throws IOException {
        // 实现将单个订单写入Excel文件的一行
        // 此处省略具体实现细节...
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值