use*_*782 9 java streaming exception spring-mvc spring-boot
我在 Spring MVC 控制器中遇到了一个关于 StreamingReponseBody 的奇怪问题。简单的控制器代码:
@RestController
public class ServerController {
@GetMapping("test")
StreamingResponseBody test(HttpServletResponse response) {
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"test.csv\"");
return outputStream -> {
for (int i = 0; i < 5000; i++) {
outputStream.write("Hello".getBytes());
outputStream.write("\n".getBytes());
}
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (true) {
throw new RuntimeException("wrong");
}
for (int i = 0; i < 5000; i++) {
outputStream.write("Hello2".getBytes());
outputStream.write("\n".getBytes());
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
再加上一个控制器建议:
@ControllerAdvice
public class CustomControllerAdvice {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleInternalServerError(Exception exception) {
System.out.println("Unexpected error " + exception);
return new ResponseEntity<>(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
Run Code Online (Sandbox Code Playgroud)
}
当我删除 throw 子句时,它就像一个魅力。当我在浏览器中输入 URL */test 时,我可以看到可以下载文件 test.csv。它会正确传输一段时间,我会收到 200 HTTP 代码,并且可以查看该文件。
然而抛出异常会导致代码做一些奇怪的事情。我没有收到 500 HTTP 代码,而是收到 200 HTTP 代码。在流的末尾,我得到一个“错误”文本(异常文本 o_O)...这里发生了什么?为什么我没有收到 500 HTTP 代码。端点发送的数据不完整,但它表示尽管有异常,但一切正常。或者我应该使用其他某种流媒体机制,因为这个机制有问题?
谢谢你的帮助!
纠正我的理解。你开始使用流发送数据,所以你(我猜)不能在某个时刻说“等待,删除我已经发送的数据并更改http状态[可能在开始发送一些数据之前设置为200]”。因此,当异常发生时,Spring 重用 OutputStream 并从以下位置放入数据:
return new ResponseEntity<>(exception.getMessage()
到同一个输出流中。
一个建议可能是包装可能在 try-catch 和 use 中抛出异常的代码,IOUtils.closeQuietly但效果是您将获得 5000x 的 Hello 和流结束(因此仍然是 200 http 状态,您正确发送的数据位于客户端,但wrong最后没有)
例子:
if (true) {
try {
throw new RuntimeException("wrong");
} catch (RuntimeException e) {
IOUtils.closeQuietly(outputStream); #apache
throw e;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2701 次 |
| 最近记录: |