第二次调用HttpServletResponse

时间:2011-04-11 19:22:55

标签: java javascript ajax web-services servlets

我正在尝试设置一个servlet,我可以使用它来异步调用webservices。在大多数情况下,它工作正常。我有一个带有doGet方法的servlet和一个调用它的js。我在js中有一个回调方法,servlet在完成它的操作后正确调用。

复杂的是,我调用的其中一个Web服务也是异步的,我希望能够在异步ws回调完成后第二次调用js回调方法。例如,如果您有一个状态字段,当您调用同步Web服务时,它会立即更新为“Beginning Synchronous Call”,然后当servlet回调到达时,它将更改为回调值,这是Web服务的结果。

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

我是AJAX和servlets的新手,所以也许这是实现我想要的一种可怕方式。

Web服务都在Servlet中调用,主要使用Netbeans自动生成的WS调用。 WS调用自身工作正常,但是一旦我得到异步WS的结果,我就陷入了webservice回调的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) { 
        }
    }
};

这不会在附加调试器的情况下编译,并且似乎无法分配引用。

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

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

启动异步调用的操作立即结束,您需要从servlet doGet方法返回(虽然从技术上讲,您可以保持servlet调用,直到您的异步调用完成,我不建议这样做,因为它占用了服务器资源一般情况下,尽快从servlet返回是一种很好的做法。

最佳行动方案是:

  1. 拥有内部数据结构(例如,具有适当同步的HashMap)来保存正在执行的异步调用。
  2. 当您开始新的呼叫时,请为其分配伪随机密钥并从初始呼叫返回。
  3. 使用上面的密钥,让浏览器端的JavaScript AJAX调用定期轮询调用状态并显示结果。
  4. 不要忘记清理已完成或过时的调用(例如,通过运行计时器线程)。
  5. 如果您对上面的步骤3中的轮询实现感到满意,您可能需要考虑Comet, a.k.a. long poll来替换客户端轮询。

答案 1 :(得分:1)

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

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