首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring MVC + StreamingResponseBody -异常导致HTTP OK

Spring MVC + StreamingResponseBody -异常导致HTTP OK
EN

Stack Overflow用户
提问于 2018-10-05 22:22:27
回答 2查看 1.6K关注 0票数 4

在我的spring MVC控制器中,我遇到了一个关于StreamingReponseBody的奇怪问题。简单的控制器代码:

代码语言:javascript
复制
    @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());
            }
        };
    }
}

再加上一个控制器的建议:

代码语言:javascript
复制
@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);
    }

}

当我删除抛出子句时,它就像一个护身符。当我在浏览器中输入URL */test时,我可以看到我可以下载文件test.csv。它被正确地流式传输了一段时间,我得到了一个200 HTTP代码,我可以查看该文件。

然而,抛出异常会导致代码做一些奇怪的事情。我收到的不是500HTTP代码,而是200HTTP代码。在流的末尾,我得到了一个“错误的”文本(异常文本o_O)...这是怎么回事?为什么我得不到500 HTTP代码。端点发送的不是完整的数据,但它说,尽管有例外,但它是可以的。或者我应该使用其他的流机制,因为这个机制有问题?

谢谢你的帮助!

EN

回答 2

Stack Overflow用户

发布于 2018-10-05 22:55:33

纠正我的理解。你开始使用stream发送数据,所以你(我猜)不能在某个时刻说“等待,删除我已经发送的数据,并在开始发送一些数据之前将http状态设置为200”。因此,当异常发生时,Spring重用OutputStream并将数据放入:

return new ResponseEntity<>(exception.getMessage()

放入相同的OutputStream中。

一种建议是包装可能在try-catch中抛出异常的代码,并使用IOUtils.closeQuietly,但结果是您将获得5000x的Hello和流结束(因此仍然是200Http状态,您正确发送的数据在客户端,但在末尾没有wrong )

示例:

代码语言:javascript
复制
if (true) {
    try {
        throw new RuntimeException("wrong");
     } catch (RuntimeException e) {
        IOUtils.closeQuietly(outputStream); #apache
        throw e;
     }
}
票数 0
EN

Stack Overflow用户

发布于 2020-07-31 10:19:01

设置一个HTTP尾部来告诉客户端一切正常!或者在可以的情况下切换到gRPC -在流上处理gRPC错误感觉更自然,客户端连接并为onError、onNext和onComplete事件提供回调。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52667734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档