【问题标题】:JAX-RS and Long PollingJAX-RS 和长轮询
【发布时间】:2013-11-01 20:08:33
【问题描述】:

我正在尝试对 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 方法中的线程创建。然后它可以工作,但问题是线程很忙。如果我使用线程创建,则方法直接返回,浏览器未检测到长轮询结束。

我做错了什么?

【问题讨论】:

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


    【解决方案1】:

    我找到了我的问题的解决方案。问题出在配置中。我们必须指定 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-supported 到 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 会再次调用该方法,否则我会处理页面中的某些内容。

    【讨论】:

    • 您是如何发现不需要显式创建线程的?在 Jersey 文档的示例中,他们确实创建了线程:jersey.java.net/documentation/latest/async.html
    • 我已经看到了。我认为这是示例中的问题。线程不应该由代码本身创建,否则异步请求有什么好处?此外,这无需手动创建线程即可工作。如果 'async-supported' 支持为 true,则应用程序服务器创建线程。我使用调试器进行了检查。
    • 但是您是不是缺少 poll 方法中的“@ManagedAsync”注释?见jersey.java.net/apidocs/2.7/jersey/org/glassfish/jersey/server/…
    • 或者“@ManagedAsync”可能只是一种更具体的方式(在方法级别)告诉 Jersey 它必须为异步方法创建一个线程,而不是 true 在 servlet 级别工作
    • 你是对的。 @ManagedAsync 是泽西岛特有的。我通常更喜欢标准方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2011-12-16
    • 1970-01-01
    • 2013-03-15
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多