Spring MVC 3.2 预览:介绍 Servlet 3 异步支持

工程 | Rossen Stoyanchev | 2012 年 5 月 7 日 | ...

最后更新于 2012 年 11 月 5 日 (Spring MVC 3.2 RC1)

概述

Spring MVC 3.2 引入了基于 Servlet 3 的异步请求处理。这是涵盖此新功能的多篇博文中的第一篇,并提供了理解如何以及为何使用它的背景。

早期发布的主要目的是寻求反馈。自 3.2 M1 版本发布以来,我们在这里和 JIRA 中收到了大量反馈。感谢所有尝试并发表评论的人!有无数的更改,还有时间接受更多反馈!

一览

从编程模型角度来看,新功能看似非常简单。控制器方法现在可以返回一个 java.util.concurrent.Callable 以异步完成处理。然后,Spring MVC 将在 TaskExecutor 的帮助下,在一个单独的线程中调用 Callable。这是一段之前的代码片段。


// Before
@RequestMapping(method=RequestMethod.POST)
public String processUpload(final MultipartFile file) {
    // ...
    return "someView";
}

// After
@RequestMapping(method=RequestMethod.POST)
public Callable<String> processUpload(final MultipartFile file) {

  return new Callable<String>() {
    public Object call() throws Exception {
      // ...
      return "someView";
    }
  };
}

控制器方法还可以返回一个 DeferredResult(Spring MVC 3.2 中的新类型)以在 Spring MVC 未知的线程中完成处理。例如,响应 JMS 或 AMQP 消息、Redis 通知等。这是另一段代码片段。


@RequestMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
  DeferredResult<String> deferredResult = new DeferredResult<String>();
  // Add deferredResult to a Queue or a Map...
  return deferredResult;
}


// In some other thread...
deferredResult.setResult(data);
// Remove deferredResult from the Queue or Map

上述示例引出了许多问题,我们将在后续的博文中详细介绍。现在,我将首先提供一些关于这些功能的背景信息。

Web应用程序异步化的动机

Web应用程序异步化的最基本动机是处理耗时较长的请求。可能是缓慢的数据库查询、对外部REST API的调用,或其他一些I/O密集型操作。这些耗时较长的请求会迅速耗尽Servlet容器的线程池,影响可伸缩性。

在某些情况下,您可以在后台作业完成处理的同时立即返回给客户端。例如,发送电子邮件、启动数据库作业以及其他“即发即弃”(fire-and-forget)场景,这些可以通过Spring的 @Async 支持,或者通过将事件发布到 Spring Integration 通道来处理,然后返回一个客户端可以使用该确认ID来查询结果。

在其他需要结果的情况下,我们需要将处理与Servlet容器线程解耦,否则我们将耗尽其线程池。Servlet 3提供了这样的支持,其中Servlet(或Spring MVC控制器)可以在Servlet容器线程退出后指示响应保持打开状态。

为了实现这一点,Servlet 3 Web应用程序可以调用 request.startAsync() 并使用返回的 AsyncContext 从其他独立线程继续写入响应。同时,从客户端的角度来看,请求仍然像任何其他HTTP请求-响应交互一样。只是完成需要更长时间。以下是事件序列:

  1. 客户端发送请求
  2. Servlet容器分配一个线程并在其中调用一个Servlet
  3. Servlet调用 request.startAsync(),保存 AsyncContext,然后返回
  4. 容器线程完全退出,但响应保持打开状态
  5. 其他线程使用已保存的 AsyncContext 完成响应
  6. 客户端接收响应

当然,Servlet异步支持还有很多内容。您可以找到 各种 示例文档,但以上总结了您需要了解的基本、最低概念。 下一篇博文 将介绍异步请求处理的第二个动机——浏览器接收实时信息更新的需求。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有