Spring DeferredResult设置结果不恢复请求

时间:2015-02-19 09:20:32

标签: java spring spring-mvc long-polling asynchronous

我在使用Spring DeferredResult时遇到了一些问题,我想我误解了一些关于它们的问题。 这些DeferredResult用于长轮询。

我有一个应用程序,可以登录多个用户,并显示数据库中的项目列表。所有连接的用户都可以看到相同的项目。任何用户都可以在给定时间选择其中一个项目并与之交互,但其他用户不能再与该特定项目进行交互(比如项目是"锁定"其他用户很快当有人选择它直到用户"发布"它)。

无论如何,我使用长轮询来通知其他人一个用户""一个项目,这是项目现在"锁定",以更新他们的界面。

假设我有例如一个用于民意调查的网址: /polling和其他人:/take/{itemId}

我有一个使用Spring MVC和#34;旧式&#34;的Web应用程序。带有异步进程参数的XML配置: 我的servlet配置中<task:annotation-driven>,更重要的是(我认为)<async-supported>true</async-supported>中的web.xml

当用户拨打/polling时,请求将返回DeferredResult

private final BlockingQueue<DeferredResult<List<MyItem>>> pendingRequests = new LinkedBlockingQueue<>();

@RequestMapping("/polling")
public DeferredResult<List<MyItem>> poll(...) {
    final DeferredResult<List<MyItem>> def = new DeferredResult<>(60000l);
    // ... deferred result init like set onCompletion(), onTimeout()...

    // add the deferred to a queue
    pendingRequests.add(def);
    return def;
}

然后,当用户&#34;采取&#34;一个项目并调用/take/{itemId},如下所示:

@RequestMapping("/take/{itemId}")
public void takeItem(...) {
    // ..marking the item as taken and saving it into DB..
    // and then, notifying the other pending requests
    // the item has been taken by someone
    List<MyItem> updatedItemsList = getLastItemsFromDb();
    for (DeferredResult<...> d : pendingRequests) {
        d.setResult(updatedItemsList);
    }
}

请注意,在updatedItemsList列表中,特定内容现在标记为&#34;已采取&#34;。

所以在这里,这似乎工作正常。在对每个项目设置结果后,相应的请求立即恢复并且&#34;中断&#34;长轮询过程无需等待请求超时,以便前面的javascript可以更新列表并发出新的长请求。

问题是我最近试图&#34;转换&#34;这个Web应用程序使用Spring Boot,以及所有基于Java / annotation的&#34;组态。 而且这种行为不再起作用了。实际上,它就像设置DeferredResult(在第二个请求中的for循环中)不再触发恢复请求,并且必须等待超时到返回结果。

但是,我发现在setResult中调用DeferredResult对象上的TaskExecutor方法会使一切都像以前一样。

我的问题是,为什么?为什么这种方式适用于XML样式的配置,没有任何执行程序或显式后台setResult()调用,这对基于Java的配置不再起作用了? 我错过了什么吗?

仅供参考,Java配置相当&#34;经典&#34;,我设置@EnableAutoConfiguration@EnableAsync,从WebMvcConfigurerAdapter延伸。

提前感谢您阅读本文并抽出时间回复!

0 个答案:

没有答案