在一个下载需求中,为了优化用户体验,在服务端的数据处理前加入了以下代码:
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方法前面很多地方都是一致的,这就很奇怪了。
我只好求助网上,然后就看到了这个:
难道浏览器也是这样的吗??
我赶忙去验证,修改了下代码:
@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”…
果然是这样。
最后的总结就是:
一开始我的认知是对的,之所以浏览器出现这样的现象,是因为它是按行解析,所以虽然没有看到消息,但其实它已经收到了,只是没有显示出来而已。这个可能也跟返回的数据类型有关,如果是二进制流或者文件,可能也不会出现这样的问题。