1

我无法为用户建立 AsyncContexts 并使用它们向他们推送通知。在页面加载时,我有一些 jQuery 代码来发送请求:

$.post("TestServlet",{
    action: "registerAsynchronousContext"
        },function(data, textStatus, jqXHR){
            alert("Server received async request"); //Placed here for debugging   
  }, "json");

在“TestServlet”中,我在 doPost 方法中有以下代码:

HttpSession userSession = request.getSession();
String userIDString = userSession.getAttribute("id").toString();

String paramAction = request.getParameter("action");

if(paramAction.equals("registerAsynchronousContext"))
{              
    AsyncContext userAsyncContext = request.startAsync();

    HashMap<String, AsyncContext> userAsynchronousContextHashMap = (HashMap<String, AsyncContext>)getServletContext().getAttribute("userAsynchronousContextHashMap");
    userAsynchronousContextHashMap.put(userIDString, userAsyncContext);
    getServletContext().setAttribute("userAsynchronousContextHashMap", userAsynchronousContextHashMap);

    System.out.println("Put asynchronous request in global map");
}

    //userAsynchronousContextHashMap is created by a ContextListener on the start of the web-app

但是,根据 Opera Dragonfly(一种调试工具,如 Firebug),似乎服务器在请求发送后大约 30000 毫秒发送了 HTTP 500 响应。

使用 userAsyncContext.getResponse().getWriter().print(SOME_JSON) 创建并在 HTTP 500 响应之前发送的任何响应都不会被浏览器接收,我不知道为什么。仅当处理 AsyncContext 的“if”语句中的所有代码都不存在时,浏览器才会接收使用常规响应对象发送响应 (response.print(SOME_JSON))。

有人可以帮我吗?我有一种感觉,这是由于我对异步 API 的工作原理有误解。我认为我可以将这些 AsyncContexts 存储在全局映射中,然后检索它们并使用它们的响应对象将内容推送给客户端。但是,似乎 AsyncContexts 不能写回客户端。

任何帮助将不胜感激。

4

2 回答 2

5

我解决了这个问题。我的方法似乎有几个问题:

  1. 在 Glassfish 中,AsyncContext 对象都具有 30,000 毫秒(0.5 分钟)的默认超时时间。一旦此期限到期,整个响应将提交回客户端,这意味着您将无法再次使用它。

    如果您正在实现长轮询,这可能不是什么大问题(因为无论如何您最终都会在响应之后发送另一个请求),但是如果您希望实现流式传输(将数据发送回客户端而不提交响应)你会想要增加超时,或者一起摆脱它。这可以通过 AsyncContext 的.setTimeout()方法来完成。请注意,虽然规范声明:“超时值为零或更小表示没有超时。”,Glassfish(此时)似乎将 0 解释为“需要立即响应”,任何负数都解释为“没有超时”。

  2. 如果您正在实现流式传输,则必须在使用其或方法写入数据.flush()后使用 printwriter 的方法将数据推送到客户端。.print() .println().write()

  3. 在客户端,如果您已流式传输数据,它将触发 3 的 readyState(“交互式”,这意味着浏览器正在接收响应)。如果您使用 jQuery,则没有简单的方法来处理 3 的 readyStates,因此如果您正在实施流式传输,您将不得不恢复为常规 Javascript 以便发送请求和处理响应。

于 2011-05-11T05:30:40.340 回答
2

我注意到在 Glassfish 中,如果您使用 AsyncContext 并将 .setTimeOut() 设置为负数,无论如何连接都会中断,要解决此问题,我必须使用 Glassfish 管理 Web 配置器:asadmin set configs.config.server-config。 network-config.protocols.protocol.http-listener-1.http。并将超时设置为-1。所有这些都是为了避免 glassfish 在 30 秒后完成连接。

于 2012-06-25T22:18:03.880 回答