偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

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

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

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

大文件下載:秒級(jí)傳輸,避免內(nèi)存溢出

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

代碼示例:

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);
    }
}

關(guān)鍵點(diǎn):

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

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

對(duì)于日志監(jiān)控、股票行情等實(shí)時(shí)更新的數(shù)據(jù),傳統(tǒng)方案往往需要輪詢獲取數(shù)據(jù),帶來(lái)額外的網(wǎng)絡(luò)開銷。使用 StreamingResponseBody,可以建立長(zhǎng)連接,讓服務(wù)器主動(dòng)推送最新數(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);
    }
}

關(guān)鍵點(diǎn):

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

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

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

代碼示例:

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);
    }
}

關(guān)鍵點(diǎn):

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

總結(jié)

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

責(zé)任編輯:武曉燕 來(lái)源: 路條編程
相關(guān)推薦

2025-04-07 02:33:00

項(xiàng)目開發(fā)Spring

2025-06-11 04:44:00

技巧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網(wǎng)絡(luò)技巧

2025-05-14 08:20:00

Linux權(quán)限管理sudo

2009-08-26 08:42:09

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

2025-06-11 09:28:22

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內(nèi)存

2011-08-10 09:06:44

內(nèi)存內(nèi)存優(yōu)化

2010-04-15 16:03:19

Hyper-V災(zāi)難恢復(fù)

2021-08-17 11:20:25

Vue前端技巧

2024-12-03 11:29:31

Javathis變量
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)