我在使用Spring DeferredResult
时遇到了一些问题,我想我误解了一些关于它们的问题。
这些DeferredResult
用于长轮询。
我有一个应用程序,可以登录多个用户,并显示数据库中的项目列表。所有连接的用户都可以看到相同的项目。任何用户都可以在给定时间选择其中一个项目并与之交互,但其他用户不能再与该特定项目进行交互(比如项目是"锁定"其他用户很快当有人选择它直到用户"发布"它)。
无论如何,我使用长轮询来通知其他人一个用户""一个项目,这是项目现在"锁定",以更新他们的界面。
假设我有例如一个用于民意调查的网址:
/polling
和其他人:/take/{itemId}
我有一个使用Spring MVC和#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
延伸。
提前感谢您阅读本文并抽出时间回复!