Tomcat不会刷新响应缓冲区

我在下面的Tomcat 7上测试了HttpResponse#flushBufferPrintWriter#flush HttpResponse#flushBuffer ,但似乎响应忽略了它们而不是像预期的那样在线上刷新内容。

 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”。 这是不正当行为还是打算?

@编辑

根据@Tomasz Nurkiewicz的建议,我再次用curl测试然后问题就消失了。 似乎标准浏览器和tcp/ip monitor从同一个http响应中打包small pieces of contents以将它们一起呈现。

@EDIT 2

还观察到HttpResponse#flushBufferPrintWriter#flush驱动Tomcat 7发送客户端分块数据 。

flushBuffer()的API非常精确:

强制将缓冲区中的任何内容写入客户端 。 对此方法的调用会自动提交响应,这意味着将写入状态代码和标头。

因此,根据规范没有实现Tomcat(更积极地缓冲并且如果它们太小则保持刷新)或者客户端(浏览器)在实际呈现之前等待更多输入。

你可以尝试使用curl或nc吗?

我刚才有同样的问题。 要阻止浏览器等待页面完成加载,然后才能进行任何渲染,您需要从以下开始:

 response.setContentType("text/html;charset=UTF-8"); 

我也有这个问题。 而且我也发现问题随着curl而消失。 通过一些嗅探,结果certificate罪魁祸首是gzip编码。 为了压缩响应,gzip一直等到底层PrintWriter关闭(也就是说,直到写完全响应),然后产生压缩输出。 在客户端,这意味着在完整响应准备好之前,您不会得到任何回复。 另一方面,Curl不向服务器发出Accept-Encoding:gzip,这就是为什么这样做的原因,你可以按照预期正常获得分块输出。

这种现象的一个尚未提及的可能原因是反病毒软件。 我确实在我的机器上观察到相同的行为:服务器发送分块数据,curl工作,普通浏览器没有,并且Fiddler也确认它不是阻止的服务器。 所以过了一段时间我怀疑Sophos(我的雇主使用的反病毒软件)的网络保护干扰,事实上他们确认他们阻止了https://community.sophos.com/kb/en-us/115656除了通常用于流媒体数据的某些mime类型之外,分块数据直到响应完成。

作为快速检查,可以在http://www.pushlets.com上运行HTTP-Push演示。 如果它不起作用,很可能客户端在处理text / html类型的分块数据方面存在一般性问题。