Java Servlet:为什么 PrintWriter.flush() 不刷新?

发布于 2024-07-26 17:07:53 字数 2434 浏览 4 评论 0原文

我目前正在编写一个 Comet 应用程序,它要求我在持久连接上一次发送大量数据。 但是,在关闭连接之前我无法将消息刷新到客户端。 PrintWriter.flush() 方法没有像我想象的那样表现有什么原因吗?

这是我的 Tomcat Comet 实现:

public void event(CometEvent event) throws IOException, ServletException {
    HttpServletRequest request = event.getHttpServletRequest();
    HttpServletResponse response = event.getHttpServletResponse();
    if (event.getEventType() == EventType.BEGIN) {
        request.setAttribute("org.apache.tomcat.comet.timeout", 300 * 1000);
        PrintWriter out = response.getWriter();
        out.println("BEGIN!");
        out.flush();
        System.out.println("EventType.BEGIN");
    } else if (event.getEventType() == EventType.READ) {
        InputStream is = request.getInputStream();
        byte[] buf = new byte[512];
        do {
            int n = is.read(buf); //can throw an IOException
            if (n > 0) {
                System.out.println("Read " + n + " bytes: " + new String(buf, 0, n) 
                        + " for session: " + request.getSession(true).getId());
            } else if (n < 0) {

                return;
            }
        } while (is.available() > 0);
        System.out.println("subtype: "+event.getEventSubType());
        System.out.println("EventType.READ");
    } else if (event.getEventType() == EventType.END) {
        PrintWriter out = response.getWriter();
        out.println("END!");
        out.close();
        System.out.println("checkError: "+out.checkError());
        System.out.println(event.getEventSubType());
        System.out.println("EventType.END");
        //eventWorker.enqueue(new EndEvent(request, response));
    } else if (event.getEventType() == EventType.ERROR) {
        PrintWriter out = response.getWriter();

        out.println("ERROR!");
        out.flush();
        System.out.println("checkError: "+out.checkError());
        System.out.println("subtype: "+event.getEventSubType());

        //response.getWriter().close();
        System.out.println("EventType.ERROR");
    } else {
        (new ServletException("EXCEPTION")).printStackTrace();
    }
}

所以在这里我尝试发送消息“开始!” 然后保持连接打开,以便我可以发送更多数据。 但是,在连接关闭之前,消息似乎不会传递。

这是我的ajax代码: $.post('comet', function(data) {alert(data); });

运行此代码后,Firebug 告诉我这是响应标头: 服务器:Apache-Coyote/1.1 传输编码:分块 日期:2009 年 7 月 13 日星期一 21:16:29 GMT

这让我认为我的浏览器收到了一些返回的数据,但如何在连接关闭之前更新页面上的某些内容?

I am currently writing a Comet application which requires me to send chunks of data at a time on a persistent connection. However, I'm having trouble flushing the message to the client before closing the connection. Is there any reason the PrintWriter.flush() method is not behaving like I think it should?

This is my Tomcat Comet implementation:

public void event(CometEvent event) throws IOException, ServletException {
    HttpServletRequest request = event.getHttpServletRequest();
    HttpServletResponse response = event.getHttpServletResponse();
    if (event.getEventType() == EventType.BEGIN) {
        request.setAttribute("org.apache.tomcat.comet.timeout", 300 * 1000);
        PrintWriter out = response.getWriter();
        out.println("BEGIN!");
        out.flush();
        System.out.println("EventType.BEGIN");
    } else if (event.getEventType() == EventType.READ) {
        InputStream is = request.getInputStream();
        byte[] buf = new byte[512];
        do {
            int n = is.read(buf); //can throw an IOException
            if (n > 0) {
                System.out.println("Read " + n + " bytes: " + new String(buf, 0, n) 
                        + " for session: " + request.getSession(true).getId());
            } else if (n < 0) {

                return;
            }
        } while (is.available() > 0);
        System.out.println("subtype: "+event.getEventSubType());
        System.out.println("EventType.READ");
    } else if (event.getEventType() == EventType.END) {
        PrintWriter out = response.getWriter();
        out.println("END!");
        out.close();
        System.out.println("checkError: "+out.checkError());
        System.out.println(event.getEventSubType());
        System.out.println("EventType.END");
        //eventWorker.enqueue(new EndEvent(request, response));
    } else if (event.getEventType() == EventType.ERROR) {
        PrintWriter out = response.getWriter();

        out.println("ERROR!");
        out.flush();
        System.out.println("checkError: "+out.checkError());
        System.out.println("subtype: "+event.getEventSubType());

        //response.getWriter().close();
        System.out.println("EventType.ERROR");
    } else {
        (new ServletException("EXCEPTION")).printStackTrace();
    }
}

So here I'm trying to send the message "BEGIN!" and keep the connection open afterwards so I can send more data. However, it seems that the message doesn't go through until the connection is closed.

This is my ajax code:
$.post('comet', function(data) { alert(data); });

After I run this code, Firebug tells me that this is the response header:
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Mon, 13 Jul 2009 21:16:29 GMT

This leads me to think that my browser received some data back, but how do I update something on the page before the connection is closed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

分開簡單 2024-08-02 17:07:53

所以看起来浏览器一直在接收数据,但由于连接没有关闭,JavaScript 认为数据仍在发送。 这就是为什么我的 jQuery 回调函数没有被调用。

查看 W3C AJAX 教程,我注意到 XMLHttpRequest 对象有不同的就绪状态。

var xmlhttp;
    if (window.XMLHttpRequest)
      {
      // code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else if (window.ActiveXObject)
      {
      // code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    else
      {
      alert("Your browser does not support XMLHTTP!");
      }
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==3) {
            alert('process '+xmlhttp.responseText);
        }
        if(xmlhttp.readyState==4) {
            alert('ready '+xmlhttp.responseText);
        }
    }
    xmlhttp.open("GET","comet",true);
    xmlhttp.send(null);

传统上,人们只处理第四个就绪状态,这意味着传输已完成。 然而,就我而言,我需要在传输结束之前读取数据。 因此,我需要代码来处理第三个就绪状态。

So it seems that the browser was receiving data this whole time, but because the connection wasn't closed, the JavaScript thought data was still being sent. This is why my jQuery callback function was not being called.

Looking at the W3C AJAX tutorial, I noticed that there are different ready states for the XMLHttpRequest object.

var xmlhttp;
    if (window.XMLHttpRequest)
      {
      // code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else if (window.ActiveXObject)
      {
      // code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    else
      {
      alert("Your browser does not support XMLHTTP!");
      }
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==3) {
            alert('process '+xmlhttp.responseText);
        }
        if(xmlhttp.readyState==4) {
            alert('ready '+xmlhttp.responseText);
        }
    }
    xmlhttp.open("GET","comet",true);
    xmlhttp.send(null);

Traditionally, people only handle the 4th readyState, which means transfer is complete. In my case, however, I needed to read data before the transfer ends. Hence, I needed code to handle the 3rd readyState.

鹊巢 2024-08-02 17:07:53

我记得 servlet 存在一个问题,如果您的页面被重定向(如错误页面),则当前响应缓冲区(在本例中为 writer)将被丢弃而不会被写入。

I remember there being an issue with servlets where if your page is redirected (like to an error page) the current response buffer, writer in this case, is thrown away without being written.

烟花易冷人易散 2024-08-02 17:07:53

我真的不明白妙语。

因此,一旦出现错误并且连接关闭,我就会看到之前尝试发送的所有消息。

这意味着什么? 另外,您可能想查看 api 中的 available()。 我不认为它会起到你认为的作用。

I don't really follow the punchline.

So once there is an error and the connection closes, I see all the messages that I tried to send earlier.

what does that mean? Also, you might want to check out the api for available(). I don't think it does what you think it does.

夏尔 2024-08-02 17:07:53

我遇到了几乎同样的问题:

两次通话都没有结果。

writer.flush();
writer.end();

当我尝试在上面两个之外执行 response.flushBuffer() 时,抛出了 java.nio.charset.UnmappableCharacterException (在 jboss 5.1 下)。 然后我添加了一个 response.setCharacterEncoding("UTF-8); ,问题就消失了。

这可能与您的问题无关,但由于我发现您的帖子是谷歌中的第一个帖子,所以我回答这里是为有同样情况的人准备的。

I had nearly the same problem:

Both calls and nothing going out.

writer.flush();
writer.end();

When I attempted to do a response.flushBuffer() in addition to the two above, a java.nio.charset.UnmappableCharacterException was thrown (under jboss 5.1). I then added a response.setCharacterEncoding("UTF-8); and the problem is gone.

This has probably nothing to do with your problem but since I found your post as the first in google, I answer it here for people having the same situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文