【问题标题】:Java Servlet 3.0 server push: Sending data multiple times using same AsyncContextJava Servlet 3.0 服务器推送:使用相同的 AsyncContext 多次发送数据
【发布时间】:2013-05-23 04:58:20
【问题描述】:

由这里回答的几个例子和问题引导(主要是 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 8 继续API,我还尝试使用打印到OutputStream 而不是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);

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

【问题讨论】:

  • 你能发布你的xml配置吗?
  • 这个 servlet 没有 XML 配置,它的 3.0 规范并配置了注释(见上文,asyncSupported = true)但是,如果我将其设置为 false,则 servlet 在startAsync() 行上失败。所以它的配置很好。此外,当我从 cmd 运行 curl 到该地址时,它按预期以块的形式显示数据。所以我的结论是客户端的JS代码是错误的。
  • 这对你有用吗?
  • 不,它没有。抱歉我没有早点回复。我用 jQuery .ajax 调用和 XMLHttpRequest 都试过了。请求待处理,永远不会触发readystatechange
  • Nob,你能告诉我我的新答案是否适合你吗?或者你有没有想出其他方法来解决它?无论如何,我有兴趣知道。谢谢!

标签: java jakarta-ee servlets servlet-3.0 server-push


【解决方案1】:

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

我获取了您的客户端代码,并且能够看到增量响应,只有只有一点点变化:

response.setContentType("text/html");

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

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

【讨论】:

  • 感谢您的努力,直到现在才看到。我会试试看!我真的被其他问题的atm淹没了。 :) 我一试就会通知你。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2016-09-27
    • 2014-03-13
    • 1970-01-01
    • 2016-09-01
    相关资源
    最近更新 更多