4

我正在尝试对 JAX-RS(Jersey 实现)使用长轮询,但它没有按我预期的那样工作。也许我误解了什么。我会很感激任何建议。

请注意,出于安全原因,不能使用反向连接(例如 Atmosphere、Comet 等)。并不是说我目前正在使用 Tomcat 7 进行开发。

以下方法是从 JQuery Ajax 调用中调用的(使用$.ajax)。

@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
        throws InterruptedException {
    new Thread(new Runnable() {
        @Override
        public void run() {
            this.asyncResponse = asyncResponse;
            // wait max. 30 seconds using a CountDownLatch
            latch.await(getTimeout(), TimeUnit.SECONDS);
        }
    }).start();
}

另一种方法是从我的应用程序中调用的(在 JMS 调用之后):

@POST
@Path("/printed")
public Response printCallback() {
    // ...

    // I expect the /poll call to be ended here from the client perspective but that is not the case
    asyncResponse.resume("UPDATE"); 
    latch.countDown();

    return Response.ok().build();
}

如果我删除方法中的线程创建poll。然后它可以工作,但问题是线程很忙。如果我使用线程创建,则该方法直接返回并且浏览器没有检测到长轮询的结束。

我究竟做错了什么?

4

1 回答 1

4

我找到了我的问题的解决方案。问题出在配置中。我们必须指定 Jersey servlet 支持async,然后它才能正常工作:

<servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <async-supported>true</async-supported>
    ...
</servlet>

async-supported请注意,如果您有 Servlet 过滤器,它们也需要true.

这也不是创建线程所必需的。泽西岛为我做到了:

@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
        throws InterruptedException {
    asyncResponse.setTimeout(30, TimeUnit.SECONDS);
    this.asyncResponse = asyncResponse;
}

@POST
@Path("/printed")
public Response printCallback(String barcode) throws IOException {
    // ...

    this.asyncResponse.resume("MESSAGE");

    return Response.ok().build();
}

调用poll浏览器时,如果超时,则等待直到接收MESSAGE或接收到 HTTP 状态 503。在服务器中,请求线程直到超时才被阻塞,而是直接释放。在客户端,如果发生超时,我有一个 JavaScript 会再次调用该方法,否则我会处理页面中的某些内容。

于 2013-10-28T07:52:08.653 回答