我有一个 servlet,映射到一个 URL,它执行很长的任务并在工作时输出一些数据。
我想做的是调用这个 url 并实时查看输出。
我们以此为例:
package com.tasks;
public class LongTaskWithOutput extends HttpServlet {
private static final long serialVersionUID = 2945022862538743411L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("Content-Type", "text/plain");
PrintStream out = new PrintStream(response.getOutputStream(), true);
for(int i=0; i<10;i++) {
out.println("# " + i);
out.flush();
try {
Thread.sleep(1000);
} catch(Exception e){}
}
}
}
在 web.xml
中包含以下内容:
...
<servlet>
<servlet-name>LongTaskServlet</servlet-name>
<servlet-class>com.tasks.LongTaskWithOutput</servlet-class>
<description>Long Task Servlet</description>
</servlet>
<servlet-mapping>
<servlet-name>LongTaskServlet</servlet-name>
<url-pattern>/longTask</url-pattern>
</servlet-mapping>
...
会发生什么
如果我浏览 localhost/myApp/longTask
,浏览器会让我等待 10 秒,然后立即打印出所有文本。
应该发生什么
文本一写入输出流就应该发送给浏览器,浏览器应该每秒渲染一行。
如您所见,我已经放置了一个 out.flush()
来确保流每秒刷新一次,但它仍然不起作用。
我也尝试使用 response.flushBuffer()
,但结果相同。
有什么办法可以实现吗?
更新
作为@MadConan建议,我尝试直接使用输出流:
OutputStream out = response.getOutputStream();
for(int i=0; i<10;i++) {
out.write(("# " + i + "\n").getBytes());
out.flush();
try {
Thread.sleep(1000);
} catch(Exception e){}
}
不幸的是,结果还是一样。
最佳答案
这是一个上游问题。浏览器不一定会在收到数据时显示该数据。它可能会等到请求完成。如果您要通过代理,您可能会有额外的分块。如果您窥探网络流量,我敢打赌它会按预期通过。
关于java - 流式输出java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30261649/