java / intermediate
Snippet
Speicherarme Übertragung großer Dateien via StreamingResponseBody
Das vollständige Laden riesiger Datensätze in den Arbeitsspeicher führt zu OutOfMemoryError-Abstürzen. Mit StreamingResponseBody schreibt Spring MVC Daten blockweise über einen asynchronen Worker-Thread direkt in den HTTP-OutputStream des Clients, wodurch der Heap-Verbrauch konstant bleibt.
snippet.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@RestController@RequestMapping("/export")public class DataExportController {private final LargeDatasetService datasetService;public DataExportController(LargeDatasetService datasetService) {this.datasetService = datasetService;}@GetMapping("/records")public ResponseEntity<StreamingResponseBody> streamExport() {StreamingResponseBody stream = outputStream -> {try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {datasetService.streamRecords(record -> {writer.write(record.toCsvLine());writer.newLine();});writer.flush();}};return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=export.csv").contentType(MediaType.TEXT_PLAIN).body(stream);}}
spring
Erklärung
1
StreamingResponseBody stream = outputStream -> { ... };
Definiert einen funktionalen Callback, den Spring asynchron mit direktem Zugriff auf den Client-OutputStream ausführt.
2
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)))
Ummantelt den Rohdaten-Stream mit einem gepufferten Writer für effiziente Textausgabe.
3
datasetService.streamRecords(record -> { ... });
Verarbeitet Datensätze zeilenweise aus der Persistenzschicht, ohne die gesamte Liste im RAM zu halten.
4
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=export.csv")
Weist den Browser an, den eingehenden Bytestrom als CSV-Dateidownload zu behandeln.