我在下面的HttpResponse#flushBuffer
上测试了PrintWriter#flush
和Tomcat 7
,但似乎响应忽略了它们,而不是像预期的那样在线上刷新内容。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
pw.println("say hi now");
pw.flush();
response.flushBuffer();
try {
Thread.sleep(5000);
} catch (Exception e) {
}
pw.println("say bye in 5 seconds");
}
}
在延迟之后,浏览器一起显示“hi”和“bye”。这是不正当行为还是打算?
@EDIT
根据@Tomasz Nurkiewicz
的建议,我再次使用curl
进行测试,然后问题就消失了。似乎标准浏览器和来自同一http响应的tcp/ip monitor
打包small pieces of contents
将它们组合在一起。
@EDIT 2
还观察到HttpResponse#flushBuffer
和PrintWriter#flush
驱逐Tomcat 7
以发送客户chunked data。
答案 0 :(得分:5)
我刚才有同样的问题。要阻止浏览器等待页面完成加载,然后才能进行任何渲染,您需要从:
开始response.setContentType("text/html;charset=UTF-8");
答案 1 :(得分:2)
flushBuffer()
的API非常精确:
强制将缓冲区中的任何内容写入客户端。对此方法的调用会自动提交响应,这意味着将写入状态代码和标题。
因此,根据规范没有实现Tomcat(缓冲区更积极,如果它们太小则保持刷新),或者客户端(浏览器)在实际渲染之前等待更多输入。
答案 2 :(得分:2)
我也有这个问题。我也发现问题随着卷曲而消失。 通过一些嗅探,结果证明罪魁祸首是gzip编码。为了压缩响应,gzip等待直到底层PrintWriter关闭(即,直到写入完整响应),然后产生压缩输出。在客户端,这意味着在完整响应准备好之前,您不会得到任何回复。另一方面,Curl不会向服务器发出Accept-Encoding:gzip,这就是为什么这个工作正常,你可以按预期正常获取分块输出。
答案 3 :(得分:0)
这种现象的一个尚未提及的可能原因是反病毒软件。我确实在我的机器上观察到相同的行为:服务器发送分块数据,curl工作,普通浏览器没有,并且Fiddler也证实它不是被阻止的服务器。所以过了一段时间我怀疑Sophos(我的雇主使用的防病毒软件)的网络保护干扰,事实上他们在https://community.sophos.com/kb/en-us/115656确认他们阻止了分块数据直到响应完成,除了某些哑剧 - 经常用于流媒体数据的类型。
作为快速检查,可以在http://www.pushlets.com运行HTTP-Push演示。如果它不起作用,很可能客户端在处理text / html类型的分块数据方面存在一般性问题。