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 容器线程池并影响可扩展性。

在某些情况下,您可以在后台作业完成处理时立即返回客户端。例如,发送电子邮件、启动数据库作业和其他一些代表启动并忘记的场景,可以使用 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 社区中所有即将举行的活动。

查看全部