0
点赞
收藏
分享

微信扫一扫

“当flush方法没把消息发送到客户端“

SDKB英文 2022-02-17 阅读 68

在一个下载需求中,为了优化用户体验,在服务端的数据处理前加入了以下代码:

response.getOutputStream().flush()
.....查询数据.......

flush方法会把响应头立即发送到客户端。

虽然以前就知道flush的作用,但毕竟没看过它的源码,突然想到一个测试:

@RequestMapping("hello")
@ResponseBody
public String hello(HttpServletRequest request,HttpServletResponse response) throws Exception {
		response.getOutputStream().write("h1".getBytes());
		response.getOutputStream().flush();
		Thread.sleep(20000);
		return "h2";
	}

在这段代码运行前,我预料中的结果应该是:客户端首先会收到“h1”,等待20s后,收到“h2”。

我启动服务端后,在浏览器中输入接口地址,回车…

结果大跌眼镜:屏幕一片空白,直到20s后,h1和h2竟然同时出现了。

难道我的认知是错的?flush不会把response中的内容发送到客户端?

我重新以debug模式启动服务,进入flush方法一步步的查看,没有看到什么奇怪的地方

为了对比,我又添加了close方法:

@RequestMapping("hello")
@ResponseBody
public String hello(HttpServletRequest request,HttpServletResponse response) throws Exception {
		response.getOutputStream().write("h1".getBytes());
		response.getOutputStream().flush();
		response.getOutputStream().close();
		Thread.sleep(20000);
		return "h2";
	}

在close方法的源码中也没有看到蹊跷的地方,倒是发现它和flush方法前面很多地方都是一致的,这就很奇怪了。

我只好求助网上,然后就看到了这个:
https://stackoverflow.com/questions/13446483/tomcat-servlet-response-blocking-problems-with-flush

难道浏览器也是这样的吗??

我赶忙去验证,修改了下代码:

@RequestMapping("hello")
@ResponseBody
public String hello(HttpServletRequest request,HttpServletResponse response) throws Exception {
		response.getOutputStream().write("h1\r\n".getBytes());
		response.getOutputStream().flush();
		Thread.sleep(20000);
		return "h2";
	}

然后启动,访问,屏幕立刻出现了“h1”,20s后,出现了“h2”…

果然是这样。

最后的总结就是:

一开始我的认知是对的,之所以浏览器出现这样的现象,是因为它是按行解析,所以虽然没有看到消息,但其实它已经收到了,只是没有显示出来而已。这个可能也跟返回的数据类型有关,如果是二进制流或者文件,可能也不会出现这样的问题。

举报

相关推荐

0 条评论