如何在 Spring MVC 中混合同步和异步请求?

Eme*_*gia 5 spring spring-mvc

(我问这个问题的目的是为了回答它。几个月前我在 Spring 论坛上问过这个问题,不久后我通过实验找到了解决方案。但我将其发布在这里,以防其他人点击同样的场景,因为我被告知这样做。)

我有一个 Spring MVC 端点/work,其处理是 IO 绑定的,可能需要几秒钟才能完成。进入Servlet 3异步请求和Spring MVC异步请求处理。我可以返回一个Callable<Foo>orDeferredResult<Foo>并释放我的 servlet 容器线程,以便在处理发生时执行一些有用的操作。

现在其他用户很可能会提出相同的请求。重复已完成的工作是没有意义的,因此我将在第一次完成时缓存工作结果,并希望返回该缓存结果。因此现在,完全相同的处理程序方法可能需要几秒钟或几毫秒才能完成。

我的问题是我只能给处理程序方法一个签名,并且我将其定义为 returns Callable<Foo>。我不知道如何消除短请求的开销;按照目前的情况,我将创建一个Callable<Foo>,将其排入长时间运行的任务后面,并等待线程池中的线程来处理它,所有这些都是为了最终提供我已经掌握的响应。我想避免这一切。

如果我使用 aDeferredResult<Foo>而不是 a Callable<Foo>,性能会更好一些,但我已经将处理从 Spring 托管线程中取出,丢失了 Spring Security 的 SecurityContext,并且用 Spring 特定的DeferredResult.

是否有一种有效的方法有时可以异步提供响应,有时可以从同一 MVC 处理程序方法同步提供响应?

Eme*_*gia 3

解决方案非常简单。如果处理程序方法返回Object,Spring 将根据结果的类型确定如何处理结果。如果返回值为 a ,它会正确触发异步处理Callable<Foo>,否则立即返回结果,避免了缓存结果已在手时的异步处理开销。