4

通过这里回答的几个示例和问题(主要是 http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html?page=3),我想让服务器发送多个响应在未完成请求的情况下向客户发送时间。当请求超时时,我创建另一个,依此类推。

我想避免长时间轮询,因为每次收到响应时我都必须重新创建请求。(这完全不是 servlet 3.0 的异步功能所针对的)。

我在服务器端有这个:

@WebServlet(urlPatterns = {"/home"}, name = "async", asyncSupported = true) 

public class CometServlet extends HttpServlet {

    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {

        AsyncContext ac = request.startAsync(request, response);

        HashMap<String, AsyncContext> store = AppContext.getInstance().getStore();

        store.put(request.getParameter("id"), ac);

    }
}

以及一个写入异步上下文的线程。

class MyThread extends Thread {
    String id, message;

    public MyThread(String id, String message) {
        this.id = id;
        this.message = message;
    }

    public void run() {
        HashMap<String, AsyncContext> store = AppContext.getInstance().getStore();
        AsyncContext ac = store.get(id);
        try {
            ac.getResponse().getWriter().print(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

但是当我提出请求时,只有当我调用时才会发送数据ac.complete()。没有它,请求将始终超时。所以基本上我想在请求完成之前让数据“流式传输”。

只是为了记一下,我已经尝试过使用Jetty 8Continuation API,我也尝试过打印 toOutputStream而不是PrintWriter. 我也尝试过flushBuffer()回应。一样。

我究竟做错了什么?

客户端是这样完成的:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:8080/home', true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 3 || xhr.readyState == 4) {
            document.getElementById("dynamicContent").innerHTML = xhr.responseText;
        }
    }
    xhr.send(null);

有人至少可以确认服务器端没问题吗?:)

4

2 回答 2

8

您的服务器端和客户端代码确实没问题。问题实际上在于您的浏览器缓冲来自您的网络服务器的文本/纯文本响应。这就是您在使用 curl 时看不到此问题的原因。

我拿走了你的客户端代码,我能够看到增量响应,只有一点点改变:

response.setContentType("text/html");

无论大小如何,增量响应都会立即出现。

如果没有该设置,当我的输出是一条小消息时,它被认为是文本/纯文本并且不会立即显示在客户端。当我不断向客户端响应添加越来越多的内容时,它会累积起来,直到缓冲区大小达到大约 1024 字节,然后整个内容都出现在客户端。然而,在那之后,小的增量立即出现(不再积累)。

于 2013-06-04T22:05:42.957 回答
0

我知道这有点老了,但你也可以在响应上刷新缓冲区。

于 2016-05-09T20:51:04.653 回答