JAX-RS和长轮询

时间:2013-10-23 13:49:22

标签: java jersey jax-rs long-polling servlet-3.0

我正在尝试使用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方法中删除了线程创建。然后它工作,但问题是线程忙。如果我使用Thread创建,那么该方法将直接返回,并且浏览器没有检测到长轮询的结束。

我做错了什么?

1 个答案:

答案 0 :(得分:3)

我找到了解决问题的方法。问题出在配置上。我们必须指定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>

请注意,如果您有Servlet过滤器,则还需要async-supportedtrue.

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

@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,如果发生超时,它会再次调用该方法,否则我会处理页面中的内容。