SPRING MVC 3.2 预览:介绍SERVLET 3,异步支持 已翻译 100%

lwei 投递于 2013/05/30 18:13 (共 5 段, 翻译完成于 06-18)
阅读 3121
收藏 5
0
加载中

概述

Spring MVC 3.2 引入了基于Servlet 3的异步请求处理。我将撰写多篇博文来介绍这种新功能,并提供环境介绍来帮助你理解为什么以及如何使用该功能,本文是系列博文的第一篇。

早期发布版本的主要目的是寻求反馈。自从3.2 M1版本发布以来,我们已经从这里和JIRA收到了足够多的反馈。感谢尝试此功能并给予评论的每一个人。我们已经进行了很多改进,并且,我们还有更多时间来获取更多反馈。

lwei
翻译于 2013/06/17 10:43
1

初识

从编程模型的角度来看,这种新功能貌似很简单。一个控制器方法能返回一个java.util.concurrent.Callable回调方法来异步的完成处理。Spring MVC将在TaskExecutor的帮助下在一个单独的线程中调用该回调方法。下面的代码是以前的写法:

// 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
上面的两个例子带来了很多问题,我们将在以后的文章中展开详细讨论。现在,我准备开始 围绕着这些新特性,介绍一些相关知识。
lwei
翻译于 2013/06/18 09:11
1

Web应用中支持“异步”的推动因素

web应用中支持异步机制的最基本的推动因素,是处理那些比较耗时的请求。比如一次缓慢的数据库查询,一次外部REST API调用, 或者是其他一些I/O密集型操作。这种耗时的请求会很快的耗光Servlet容器的线程池,继而影响可扩展性。

一些情况下,你可以立即返回客户端,而由服务器后台程序完成处理。比如发送一封电子邮件,完成一个数据库作业,以及其他类似“点着火就走人”的场景,这些都可以通过Spring的@Async或者向Spring 集成通道发送一个事件来处理,然后返回一个确认ID给客户端来查询处理结果。

lwei
翻译于 2013/06/18 09:32
1

在另一些情况下,必须要返回处理结果,那么我们就需要把处理过程从Servlet容器中解耦出来,否则我们将耗光线程池。Servlet 3提供了这种支持,Servlet (或者Spring MVC的控制器) 能够指示response在Servlet容器的线程退出之后保持开放状态。

要实现这种效果, Servlet 3 web应用可以调用request.startAsync(),然后在其他独立的线程中使用返回的AsyncContext来继续向response写入信息。同时,从客户端的角度来看,request仍然像任何其他的HTTP的request-response交互一样,只是耗费了更长的时间而已。下面是事件的顺序:

  1. 客户端发送一个请求
  2. Servlet容器分配一个线程来处理容器中的一个servlet
  3. servlet调用request.startAsync(),保存AsyncContext, 然后返回
  4. 任何方式存在的容器线程都将退出,但是response仍然保持开放
  5. 其他线程使用保存的AsyncContext来完成响应
  6. 客户端收到响应
lwei
翻译于 2013/06/18 10:04
1
Servlet异步支持当然不止这么多。你可以找到 更多  例子 和 评论,但是上面这些构成了基础,他们是你应当了解的核心概念。  下篇博文 将介绍异步请求处理的第二个推动因素 — 浏览器需要实时的获取信息更新。

相关博文

lwei
翻译于 2013/06/17 10:54
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(0)

返回顶部
顶部