2016-04-02 7 views
0

Ich denke, ich habe eine große Menge von CSV-Strings in der Datenbank und ich muss sie auf seine Anfrage an den Client übergeben.Schrittweise füllen Sie InputStream und geben Sie es mit SpringMVC zurück

Eine naive Art und Weise, dies zu tun:

@RequestMapping(value = "/{user}/ejournal", method = RequestMethod.GET, produces = "text/csv") 
public ResponseEntity<ByteArrayResource> getEJournal(@PathVariable Long userId) { 
    final byte[] documentBody = EJournal 
      .findByUser(userId) 
      .stream() 
      .collect(Collectors.joining("\n")) 
      .getBytes(); 
    return new ResponseEntity(
      new ByteArrayResource(documentBody), 
      HttpStatus.OK); 
} 

Von der Client-Seite seiner einfachen (Kotlin Codebeispiel):

val inputStream = eJournalService.getJournal(userId) 
inputStream.reader().forEachLine { line -> ... } 

Aber ich gezwungen bin, vor dem Durchlauf der gesamten Daten in den Speicher zu laden es zum Strom und offensichtlich ist es nicht effizient.

Also muss ich es irgendwie puffern, um Daten mit Paginierung mit benutzerdefinierten Leser zu lesen und Puffer an Client senden. Ich dachte, meine eigene InputStream zu implementieren, aber InputStream#read() gibt int statt String zurück und es ist ein bisschen kompliziert.

Best Practices, um dies zu tun? Ich habe versucht zu suchen, aber es gibt nur Beispiele, um ein Bild mit dem Stream zu übergeben, der bereits im Speicher ist, nicht mit gepufferter Seitennummerierung mit sequentiellen Datenbankabfragen nach Batch-Senden.

Vielen Dank im Voraus.

Antwort

0

Von the documentation

Im Folgenden sind die unterstützten Rückgabetypen:

[...]

  • ungültig, wenn das Verfahren die Antwort Griffe selbst (durch die Antwort schriftlich Inhalte direkt , Deklarieren eines Arguments vom Typ ServletResponse/HttpServletResponse für diesen Zweck)

[...]

  • A StreamingResponseBody kann auf die Antwort Output zurückgegeben werden asynchron zu schreiben; auch unterstützt als der Körper innerhalb einer ResponseEntity.

So können Sie nur tun

public StreamingResponseBody getEJournal(@PathVariable Long userId) { 
    return outputStream -> { 
     // write your lines to the outputStream here 
    }; 
} 

Sie können auch nur synchron zum Bach schrieb das HttpServletResponse als Argument Ihrer Methode ist, und dessen Ausgabestrom schreiben.

+0

Ist es möglich, 'StreamingResponseBody' mit' @ Transactional' zu verwenden? Es scheint ein Problem zu sein, es zu benutzen, da es async ist. – user2138356

+0

Ok, ich habe es synchron gemacht und bisher kein Problem. – user2138356