自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

內存優(yōu)化神器!Spring StreamingResponseBody 三大實戰(zhàn)技巧,告別 OOM!

開發(fā) 前端
StreamingResponseBody 提供了一種高效的流式數(shù)據(jù)傳輸方式,在大文件下載、實時推送、動態(tài)導出等場景下能夠顯著降低內存占用,提高系統(tǒng)吞吐量,讓你的應用更具彈性與穩(wěn)定性!?

在當前高并發(fā)、大數(shù)據(jù)量的業(yè)務場景下,傳統(tǒng)的同步響應模式往往會因內存占用過高、響應延遲大等問題,成為系統(tǒng)性能的瓶頸。Spring Boot 3.4 提供的 StreamingResponseBody 機制,可以實現(xiàn)流式數(shù)據(jù)傳輸,使數(shù)據(jù)在生成的同時直接發(fā)送至客戶端,從而避免內存中存儲完整響應的需求。

無論是大文件下載、實時日志推送,還是動態(tài)生成 CSV 數(shù)據(jù)并導出,StreamingResponseBody都能以極低的資源消耗實現(xiàn)高效數(shù)據(jù)傳輸。本文將通過以下三大典型場景,深入探討 StreamingResponseBody 的應用方式:

  1. 大文件下載流式讀取文件內容,避免 OOM 現(xiàn)象;
  2. 實時數(shù)據(jù)推送實現(xiàn)日志流、股票數(shù)據(jù)等動態(tài)內容推送;
  3. 動態(tài) CSV 生成與導出高效分頁查詢數(shù)據(jù)庫,避免字符串拼接導致的內存開銷。

大文件下載:秒級傳輸,避免內存溢出

在傳統(tǒng)的文件下載方式中,文件內容通常會被完整加載到內存中再返回給客戶端,對于大文件來說,這很容易導致內存溢出。使用 StreamingResponseBody,可以邊讀取文件邊傳輸數(shù)據(jù),確保內存占用始終處于合理水平。

代碼示例:

package com.icoderoad.controller;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
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 java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;


@RestController
@RequestMapping("/files")
public class FileDownloadController {


    @Value("file:///d:/software/OllamaSetup.exe")
    private Resource file;


    @GetMapping("/download")
    public ResponseEntity<StreamingResponseBody> downloadFile() throws Exception {
        String fileName = file.getFilename();
        StreamingResponseBody responseBody = outputStream -> {
            try (InputStream inputStream = file.getInputStream()) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    outputStream.flush();
                }
            }
        };
        return ResponseEntity.ok()
                .header("Content-Type", "application/octet-stream")
                .header("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8))
                .body(responseBody);
    }
}

關鍵點:

  • 流式讀取通過 InputStream 逐塊讀取文件內容,而非一次性加載到內存;
  • 實時寫出使用 flush() 確保數(shù)據(jù)立即發(fā)送,減少緩沖區(qū)積壓;
  • 避免超時建議在 application.yml 配置 spring.mvc.async.request-timeout=-1 以防止長時間下載失敗。

實時數(shù)據(jù)推送:高效流式傳輸日志

對于日志監(jiān)控、股票行情等實時更新的數(shù)據(jù),傳統(tǒng)方案往往需要輪詢獲取數(shù)據(jù),帶來額外的網絡開銷。使用 StreamingResponseBody,可以建立長連接,讓服務器主動推送最新數(shù)據(jù)。

代碼示例:

package com.icoderoad.controller;


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 java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Random;


@RestController
@RequestMapping("/stream")
public class RealTimeDataController {


    @GetMapping("/logs")
    public ResponseEntity<StreamingResponseBody> streamLogs() {
        StreamingResponseBody responseBody = outputStream -> {
            for (int i = 0; i < 20; i++) {
                String log = "日志數(shù)據(jù) " + i + " - " + LocalDateTime.now() + "\n";
                outputStream.write(log.getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
                Thread.sleep(new Random().nextInt(1000));
            }
        };
        return ResponseEntity.ok()
                .header("Content-Type", "text/plain;charset=utf-8")
                .body(responseBody);
    }
}

關鍵點:

  • 實時輸出調用 flush() 確保數(shù)據(jù)立即推送;
  • 模擬動態(tài)數(shù)據(jù)使用 Thread.sleep() 模擬數(shù)據(jù)產生的時間間隔;
  • 客戶端測試可使用 curl http://localhost:8080/stream/logs 觀察數(shù)據(jù)流式推送的效果。

動態(tài)生成 CSV 并下載

在導出大規(guī)模數(shù)據(jù)(如用戶數(shù)據(jù)、訂單數(shù)據(jù))時,傳統(tǒng)方式通常先將所有數(shù)據(jù)拼接成字符串再寫入文件,這容易造成內存溢出。通過 StreamingResponseBody,我們可以實現(xiàn) 邊查詢、邊寫入、邊下載 的流式導出。

代碼示例:

package com.icoderoad.controller;


import com.icoderoad.service.UserService;
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 java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;


@RestController
@RequestMapping("/export")
public class CsvDownloadController {


    private final UserService userService;


    public CsvDownloadController(UserService userService) {
        this.userService = userService;
    }


    @GetMapping("/users")
    public ResponseEntity<StreamingResponseBody> exportCsv() {
        StreamingResponseBody responseBody = outputStream -> {
            outputStream.write("ID,Name,Email\n".getBytes());
            for (int page = 0; page < 10; page++) {
                List<User> users = userService.getUsers(page, 10);
                for (User user : users) {
                    outputStream.write((user.id() + "," + user.name() + "," + user.email() + "\n").getBytes(StandardCharsets.UTF_8));
                }
                outputStream.flush();
            }
        };
        return ResponseEntity.ok()
                .header("Content-Type", "text/csv")
                .header("Content-Disposition", "attachment; filename=\"users.csv\"")
                .body(responseBody);
    }
}

關鍵點:

  • 分頁查詢每次僅查詢一部分數(shù)據(jù),避免一次性加載過多數(shù)據(jù);
  • 邊查詢邊寫入防止字符串拼接導致的內存溢出。

總結

StreamingResponseBody 提供了一種高效的流式數(shù)據(jù)傳輸方式,在大文件下載、實時推送、動態(tài)導出等場景下能夠顯著降低內存占用,提高系統(tǒng)吞吐量,讓你的應用更具彈性與穩(wěn)定性!

責任編輯:武曉燕 來源: 路條編程
相關推薦

2025-04-07 02:33:00

項目開發(fā)Spring

2024-11-19 15:22:37

2025-02-13 08:06:54

2010-08-13 14:44:26

思科路由器IOS軟件

2010-07-26 16:35:34

Perl性能

2010-07-26 12:50:45

Perl性能

2018-10-30 12:15:26

CDN網絡技巧

2009-08-26 08:42:09

思科認證考試資料CCNA實戰(zhàn)技巧

2024-06-27 08:41:21

2025-04-23 08:35:00

2022-05-10 09:33:50

Pandas技巧代碼

2024-01-10 16:46:13

Kubernetes容器

2010-08-10 10:17:44

Flex內存

2010-04-15 16:03:19

Hyper-V災難恢復

2021-08-17 11:20:25

Vue前端技巧

2011-08-10 09:06:44

內存內存優(yōu)化

2024-12-03 11:29:31

Javathis變量

2009-12-29 16:37:35

Ubuntu 9.10

2013-09-29 10:37:32

2024-11-11 10:00:00

點贊
收藏

51CTO技術棧公眾號