Java Servlet 3.0:Can';是否不发送异步响应?

Java Servlet 3.0:Can';是否不发送异步响应?,java,asynchronous,jakarta-ee,comet,servlet-3.0,Java,Asynchronous,Jakarta Ee,Comet,Servlet 3.0,我在为用户建立异步上下文并使用它们向用户推送通知时遇到问题。在页面加载时,我有一些jQuery代码来发送请求: $.post("TestServlet",{ action: "registerAsynchronousContext" },function(data, textStatus, jqXHR){ alert("Server received async request"); //Placed here for debugging

我在为用户建立异步上下文并使用它们向用户推送通知时遇到问题。在页面加载时,我有一些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
HttpSession userSession=request.getSession();
字符串userIDString=userSession.getAttribute(“id”).toString();
字符串paramAction=request.getParameter(“操作”);
if(paramAction.equals(“registerAsynchronousContext”))
{              
AsyncContext userAsyncContext=request.startAsync();
HashMap userAsynchronousContextHashMap=(HashMap)getServletContext().getAttribute(“userAsynchronousContextHashMap”);
userAsynchronousContextHashMap.put(userIDString,userAsynchContext);
getServletContext().setAttribute(“userAsynchronousContextHashMap”,userAsynchronousContextHashMap);
System.out.println(“将异步请求放入全局映射”);
}
//userAsynchronousContextHashMap由ContextListener在web应用程序启动时创建
然而,根据Opera Dragonfly(Firebug之类的调试工具)的说法,服务器似乎在发送请求后大约30000ms发送HTTP 500响应

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

有人能帮我吗?我觉得这是因为我对异步API的工作原理有误解。我认为我能够将这些异步上下文存储在全局映射中,然后检索它们并使用它们的响应对象将内容推送到客户端。然而,异步上下文似乎不能写回客户端


任何帮助都会被告知。

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

  • 在Glassfish中,AsyncContext对象的默认超时时间均为30000毫秒(.5分钟)。一旦该期限到期,整个响应将提交回客户端,这意味着您将无法再次使用它

    如果您要实现长轮询,这可能不是什么大问题(因为您最终还是会在响应之后发送另一个请求),但是如果您希望实现流式传输(将数据发送回客户端而不提交响应),您需要增加超时时间,或者将其全部删除。 这可以通过AsyncContext的
    .setTimeout()
    方法实现。请注意,虽然状态为:“超时值为零或更小表示没有超时”,但Glassfish(此时)似乎将0解释为“需要立即响应”,将任何负数解释为“没有超时”

  • 如果要实现流式处理,则必须使用printwriter的
    .flush()
    方法在使用其
    .print()
    .println()或
    方法写入数据后,将数据推送到客户端

  • 在客户端,如果您已将数据流化,它将触发readyState 3(“interactive”,这意味着浏览器正在接收响应)。如果您使用的是jQuery,那么没有简单的方法来处理3的readystate,因此如果您正在实现流式处理,您将不得不恢复到常规Javascript,以便发送请求和处理响应


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

  • 在Glassfish中,AsyncContext对象的默认超时时间均为30000毫秒(.5分钟)。一旦该期限到期,整个响应将提交回客户端,这意味着您将无法再次使用它

    如果您要实现长轮询,这可能不是什么大问题(因为您最终还是会在响应之后发送另一个请求),但是如果您希望实现流式传输(将数据发送回客户端而不提交响应),您需要增加超时时间,或者将其全部删除。 这可以通过AsyncContext的
    .setTimeout()
    方法实现。请注意,虽然状态为:“超时值为零或更小表示没有超时”,但Glassfish(此时)似乎将0解释为“需要立即响应”,将任何负数解释为“没有超时”

  • 如果要实现流式处理,则必须使用printwriter的
    .flush()
    方法在使用其
    .print()
    .println()
    方法写入数据后,将数据推送到客户端

  • 在客户端,如果您已将数据流化,它将触发readyState 3(“interactive”,这意味着浏览器正在接收响应)。如果您使用的是jQuery,那么没有简单的方法来处理3的readystate,因此如果您正在实现流式处理,您将不得不恢复到常规Javascript,以便发送请求和处理响应


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

    我注意到,在glassfish中,如果使用AsyncContext并将.setTimeOut()设置为负数,则无论如何连接都会断开,要修复此问题,我必须转到glassfish管理员web配置器:asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-1。