X.d 笔记

小Web,大世界

0%

关于PrintWriter里面的flush方法

Http有个响应头,trunk平时下载的时候,服务器会自动处理,但如果我们想自己手动分段返回是否可行呢?

写了一个代码

protected void service(final HttpServletRequest request,final HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain");
response.getWriter().write("response1");
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().write("response2");
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
}
response.getWriter().write("response3");
}

本意是程序快速响应一段内容,然后每3秒钟,有一点内容再继续点应,测试,9秒之后,一窝响应回来:结果如下
t1
很快就想到的流的flush方法没调,也就是说刚才调用的write方法实际只是相当于push之类的方法,flush方法会把push的方法pull出来,修改下代码再试一次

response.setContentType("text/plain");
response.getWriter().write("response1");
response.getWriter().flush();
try {
    Thread.sleep(3000L);
} catch (InterruptedException e) {
    e.printStackTrace();
}
response.getWriter().write("response2");
response.getWriter().flush();
try {
    Thread.sleep(3000L);
} catch (InterruptedException e) {
}
response.getWriter().write("response3");
response.getWriter().flush();
response.getWriter().close();

结果如下:每三秒响应一次。响应头里面没有 Content-length 属性,多一个 Transfer-Encoding:chunked 表示分块返回
telnet
这里的三个9说明这一段响应的长度,最后一个0说明响应已经完毕。

理论上来说,这个特性是为了加速前端响应有的,比如一个页面我们经常看到一打开一片白,然后从上到下依次出现文字,结构完成后又网页面上的图片,脚本,等就开始载入了。如果我用浏览器打开这个网站,应该每三秒一下依次展示出response1/2/3出来,可惜很遗憾,只有Firefox做到了,IE 和 Chorme 没做到,不知道后续的版本会不会有优化让这种机制有点利用空间。先记录一下。

效果图:除了 Firefox 能依次响应出123,其它浏览器都不支持,看来 Firefox 这段做的还不错
firefox

嗯,顺便试了下 JSP的内置out对象,也有个 flush方法,好像效果和 PrintWriter 的一样。所以只有out.println的时候,服务器只处于构造,响应阶段,并没有真正响应请求,代码如下。目前就只有Firefox支持的情况下,这样的功能也算无法发扬光大吧。

<% 
    out.println("response1");
    Thread.sleep(3000L);
    out.println("response2");
    out.flush();//只有这里flush了,才会输出
    Thread.sleep(3000L);
    out.println("response3");
%>