逐渐填充InputStream并使用SpringMVC返回它

时间:2016-04-02 09:04:35

标签: java spring spring-mvc jdbc inputstream

考虑到我在数据库中有大量的csv字符串,我需要根据他的请求将它们传递给客户端。

一种天真的方法:

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

从客户端来看,它直截了当(kotlin代码示例):

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

但我被迫将整个数据加载到内存中,然后将其传递给流,显然效率不高。

所以我需要以某种方式缓冲它以使用自定义读取器分页读取数据并将缓冲区发送到客户端。我想实现自己的InputStream,但InputStream#read()返回int而不是String,这有点复杂。

这样做的最佳做法是什么?我尝试搜索但是只有示例使用已经在内存中的流传递图片,而不是在批量发送后使用顺序数据库查询进行缓冲分页。

提前致谢。

1 个答案:

答案 0 :(得分:0)

来自the documentation

  

以下是支持的返回类型:

     

[...]

     
      
  • 如果方法处理响应本身(通过直接编写响应内容,为此目的声明类型为ServletResponse / HttpServletResponse的参数),则为void。
  •   
     

[...]

     
      
  • 可以返回StreamingResponseBody以异步写入响应OutputStream;也支持作为ResponseEntity中的正文。
  •   

所以你可以做到

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

您也可以通过将HttpServletResponse作为方法的参数来同步写入流,并写入其输出流。