【问题标题】:Call HttpServletResponse a second time第二次调用 HttpServletResponse
【发布时间】:2011-04-11 19:22:54
【问题描述】:

我正在尝试设置一个可用于异步调用 Web 服务的 servlet。在大多数情况下,它工作正常。我有一个带有 doGet 方法的 servlet 和一个调用它的 js。我在 js 中有一个回调方法,当 servlet 完成它的事情时它会正确调用它。

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

当你调用异步 web 服务时,update 字段立即更新为“Beginning Asynchronous Call”,并很快收到来自 servlet 的第一个回调,表明该 web 服务已被请求,因此我们将该字段更新为“Processing Web服务”之类的。问题是一旦 web 服务完成并回调 servlet,我似乎无法弄清楚如何将结果发送到 js 回调方法。

我对 AJAX 和 servlet 还很陌生,所以也许这是实现我想要的一种可怕的方式。

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) { 
        }
    }
};

这将无法在附加调试器的情况下编译,并且似乎无论如何都无法分配引用。

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

【问题讨论】:

  • 所以你正在使用 web 服务进行一些异步处理,第一次调用开始处理,第二次调用获取结果?因为 web 服务调用不是真正的异步(像所有 http 调用一样)?

标签: java javascript ajax web-services servlets


【解决方案1】:

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

启动异步调用的操作立即结束,您需要从 servlet doGet 方法返回(虽然从技术上讲,您可以留在 servlet 调用中直到异步调用完成我不建议这样做,因为它会占用服务器资源. 最好尽快从 servlet 返回)。

最好的做法是:

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

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

【讨论】:

  • 长轮询不会让服务器线程也保持绑定吗?如果我理解正确的话,在将更新推送到客户端之前,请求不会完成。
  • @road-to-yamburg - 有长轮询的实现(Jetty 和 Glassfish,不知道其他人)释放服务器线程并在需要推送时返回它。所以不,你不占用线程,但你仍然占用套接字和一点内存结构。
  • 谢谢。这对于我想要完成的事情来说听起来是可行的。试一试后,我将更新帖子的成功或失败。非常感谢!
  • 像魅力一样工作。感谢您的解释。仍在尝试围绕 servlet 和 ajax 之类的东西。
【解决方案2】:

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

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

【讨论】:

  • 感谢您的回复。我按照你和 Sasha 的建议设置了投票,它可以满足我的需要。
猜你喜欢
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 2013-09-11
相关资源
最近更新 更多