在tomcat 6中禁用彗星servlet的输出缓冲

时间:2012-04-27 14:15:38

标签: servlets buffer tomcat6 comet

我使用tomcat 6的彗星将数据推送到客户端。

我希望在连接关闭之前接收数据(对于XMLHttpRequest,就绪状态= 3),问题是tomcat 6在发送之前缓冲数据,因此我需要做出棘手的事情来实现这一点。

我已将application / x-javascript和req内容类型的请求内容类型设置为application / xml(以禁用浏览器缓存)。

我在tomcat 6中使用了很多可用的选项来禁用缓存(nio连接器中的socketBuffer = -1等等),这在我的本地tomcat 6(在windows os上)上工作(实际上,即使没有修改任何默认选项。)

但是,具有相同tomcat 6配置的事件,当我在http://jelastic.com提供的tomcat 6服务器上部署应用程序时,服务器输出缓冲区很大,我不得不发送空字节来触发输出写入器冲洗(参见下面的代码)

byte [] bytes = new byte [event.getHttpServletResponse()。getBufferSize() - new Gson()。toJson(messagesContent).getBytes()。length];   event.getHttpServletResponse()。getOutputStream()。write(new Gson()。toJson(messagesContent).getBytes()); 。event.getHttpServletResponse()的getOutputStream()写(字节)。 。event.getHttpServletResponse()的getOutputStream()平齐();

如果除了数据内容之外我不写字节,数据也不会发送到客户端。这真的很烦人,因为我发送无用的空字节,因为我必须在客户端上管理这些空字节。可怕。

有没有人有解决方案?如何禁用comet servlet输出缓冲区。对我来说似乎很明显,默认情况下应该为彗星servlet禁用输出缓冲区。听起来很奇怪。

先谢谢,

Ĵ

1 个答案:

答案 0 :(得分:3)

您是否尝试使用过滤器? 编程自定义请求和响应中的http://www.oracle.com/technetwork/java/filters-137243.html

使用装饰器模式可以控制输出。 这样做的方法是将生成响应的servlet传递给一个替代流。替代流可防止servlet在完成时关闭原始响应流。

class CharResponseWrapper extends HttpServletResponseWrapper {
    private CharArrayWriter output;
    public String toString() {
      return output.toString();
    }
    public ResponseWrapper(HttpServletResponse response) {
        super(response); 
        output = new CharArrayWriter();
    }
    public PrintWriter getWriter(){
        return new PrintWriter(output);
    }

}

所以在过滤器的doFilter方法中你得到原始的PrintWritter,传递包装器

PrintWriter out = response.getWriter();
CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, wrapper);

然后Servlet将写入CharrArrayWritter中的所有输出,这样您就可以在不缓冲的情况下获取字符串中的输出

wrapper.toString()

然后您可以修改,追加..等,然后使用原始响应输出来写入内容。

out.write(wrapper.toString());
out.close();