2011-04-11 252 views
0

我试图建立一个我可以用来异步调用webservices的servlet。大多数情况下,它工作正常。我有一个带doGet方法的servlet和一个叫它的js。我在js中有一个回调方法,servlet在完成它的事情时正确调用它。第二次调用HttpServletResponse

复杂的是,我所调用的Web服务之一也是异步的,我希望能够在异步WS回调完成后第二次调用js回调方法。例如,如果您有状态字段,则当您调用同步Web服务时,它立即更新为“开始同步调用”,然后当servlet回调到达时,它将更改为作为Web服务结果的回调值。

当您调用异步Web服务时,更新字段立即更新为“开始异步调用”,并且很快从servlet接收到第一个指示已请求Web服务的回调,因此我们将该字段更新为“Processing Web服务“或其他。问题是,一旦Web服务完成并调用回servlet,我似乎无法弄清楚如何将结果发送给js回调方法。

我在AJAX和servlets方面很新,所以也许这是一种可怕的方式来完成我想要的。

Web服务都在Servlet中调用,主要使用Netbeans自动生成的WS调用。 WS称自己工作正常,但一旦我得到异步WS的结果,我被卡在web服务回调的handleResponse方法内,并且不再有任何对我想要更新的文档的响应元素的引用。

我试图原始响应变量存储为静态成员变量,并用它在用handleResponse方法如下所示:

javax.xml.ws.AsyncHandler<WsClients.Op11Response> asyncHandler = new javax.xml.ws.AsyncHandler<WsClients.Op11Response>() { 

    public void handleResponse(javax.xml.ws.Response<WsClients.Op11Response> asyncResponse) { 
     try { 
      storedResponse.setContentType("text/xml"); 
      String returnString = asyncResponse.get().getReturn(); 
      storedResponse.getWriter().write("<returnData><content>" 
        + returnString + "</content></returnData>"); 

     } catch (Exception ex) { 
     } 
    } 
}; 

这不会附加调试器编译并似乎不能够无论如何分配一个参考。

有没有更好的方法来做到这一点?

+0

所以你正在做一些使用web服务的异步处理,第一次调用开始处理,第二次调用取得结果?因为web服务调用不是真的异步(就像所有的http调用一样)? – ThomasRS 2011-04-11 19:33:50

回答

2

HTTP的本质是,除非客户端通过轮询或保持连接打开来请求此信息,否则不能向客户端发回任何内容。

开始异步调用的操作立即结束,您需要从servlet的doGet方法返回(虽然从技术上讲,您可以留在servlet调用中,直到异步调用完成为止我不建议这样做,因为它会关闭服务器资源,一般来说,尽可能快地从servlet返回)。

作用的最好的办法是:

  1. 具有内部数据结构(例如HashMap中与适当的同步),以保持正在执行的异步调用。
  2. 当您开始新的呼叫时,将其分配给伪随机密钥并从初始呼叫返回。
  3. 使用上面的键,让浏览器端JavaScript AJAX调用周期性地轮询调用的状态并显示结果。
  4. 不要忘记清理已完成或过时的调用(例如通过运行计时器线程)。

如果您对上述步骤3中的轮询实施感到满意,则可能需要考虑使用Comet, a.k.a. long poll替换客户端轮询。

+0

不会长时间轮询保持服务器线程绑定吗?直到更新推送给客户端,如果我理解正确,请求才会完成。 – 2011-04-11 19:48:45

+0

@ road-to-yamburg - 有长轮询的实现(Jetty和Glassfish,不知道其他人),它们释放服务器线程并在需要推送时返回给它。所以不行,你不会捆绑线程,但是你仍然绑定套接字和一点点内存结构。 – 2011-04-11 20:01:34

+0

谢谢。这听起来对我正在努力完成的事情是可行的。在我给它一个旋转之后,我会更新这个帖子的成功或失败。非常感激! – 2011-04-11 20:32:13

1

Servlet无法再次发送响应。 HTTP协议是同步的,只有客户端可以发起请求 - 响应交换。

对于异步更新,您需要执行从客户端到服务器端的轮询,并在服务器端(在会话中)累积消息,直到客户端选择它们或到期。

+0

感谢您的回复。我按照你和Sasha的建议设置了投票,它满足了我的需要。 – 2011-04-11 21:45:00

相关问题