Spring 4.x官方参考文档中文版——第21章 Web MVC框架(12)
2016-06-15 14:44
423 查看
21.3.4 异步请求处理
SpringMVC 3.2介绍了基于Servlet3的异步请求处理。Controller控制器中的方法现在可以不单是返回一个值,现在还可以返回一个java.util.concurrent.Callable,也可以从Spring MVC管理的线程中返回一个值。这样的话,主要的Servlet容器的线程就被释放,可以用来处理其他请求了。Spring MVC会在TaskExecutor的帮助下,在单独的线程中调用Callable对象,并且当Callable对象返回时,这个请求会被分派回Servlet容器,使用这个Callable对象的返回值来恢复处理这个请求。下面是一个例子:
Controller控制器也可以返回一个DeferredResult实例。这种情况下,那些没有被Spring MVC所管理的返回值也能从任何线程中产生。比如:在响应中,结果可能是,在响应中产生一些类似JMS消息,定时任务等等的外部事件。下面是一个例子:
如果没有关于Servlet 3.0异步请求处理特性的知识,可能比较难理解。下面是关于Servlet3.0基础机制的要点:
通过调用request.startAsync(),能够把ServletRequest放到异步模式中。这样做会导致Servlet或任何Filters(过滤器)退出后,响应还是保持开通状态,来继续完成它的处理过程。
调用request.startAsync()返回的AsyncContext能在整个异步处理过程中使用。例如:它提供了一个方法”dispatch”,这个方法与Servlet API中的forward类似,只是不能在应用里的Servlet容器的线程中,恢复请求的处理过程。
ServletRequest提供对现有DispatcherType的访问,DispatcherType能用来在初始化的请求处理过程,一个异步的dispatch,一个forward,和其他dispatcher(分派器)类型区别开来。
记住了上面的要点,来看看下面的内容--使用Callable来处理异步请求时的事件顺序:
Controller返回一个Callable
Spring MVC开始异步处理过程,并且把Callable上交到TaskExecutor,在一个单独的线程中处理。
DispatcherServlet和所有Filter从Servlet容器中退出,但是,响应还是保持开通状态。
Callable产生了一个结果,并且Spring MVC把该请求分派回Servlet容器,来恢复处理过程。
DispatcherServlet被再次调用,并使用从Callable异步产生的结果来处理恢复的状态。
在DeferredResult中除了它取决于应用中,任何线程产生的异步结果外,它的顺序也是与Callable十分相似的:
Controller返回一个DeferredResult,并保存到它能够访问的内存中的queue或者list中。
Spring MVC开始异步处理过程。
DispatcherServlet和所有配置了的Filter退出该请求的处理的线程,但是响应还是处于开通状态。
该应用中从一些线程中设置了DeferredResult,然后Spring MVC分派该请求回Servlet容器中。
DispatcherServlet被再次调用,并使用异步产生了的结果处理恢复状态。
需要详细了解异步请求处理过程的行为或者了解为何,何时使用它,请参阅这个博客发表的系列文章。
异步请求的异常处理
如果在一个controller方法中,Callable在执行中抛出了错误会怎样?简短版的答案是:与controller方法抛出错误时发生的状况是一样的。它也是使用常规的异常处理机制。加长版答案是:当Callable抛出了异常,SpringMVC把这个Exception当作结果,分派到Servlet容器,这将导致恢复请求处理时,是使用的这个Exception,而不是一个controller方法的返回值。当使用DeferredResult时,你可以选择调用setResult或setErrorResult来处理Exception实例。
拦截异步请求
HandlerInterceptor也可以实现AsyncHandlerInterceptor来实现afterConcurrentHandlingStarted的回调。当异步的处理过程开始时,这个回调代替了postHandle和afterCompletion。
HandlerInterceptor也能注册CallableProcessingInterceptor或DefferedResultProcessingInterceptor来与一个异步请求的生命周期深度结合,例如:处理一个会超时的事件。详见AsyncHandlerInterceptor的javadoc文档。
DefferredResult类也提供如onTimeout(Runnable)和onCompletion(Runnable)的方法。详见DeferredResult的javadoc文档。
当使用Callable时,你也能用WebAsyncTask的实例来封装它,WebAsyncTask也能提供timeout和completion的注册方法。
SpringMVC 3.2介绍了基于Servlet3的异步请求处理。Controller控制器中的方法现在可以不单是返回一个值,现在还可以返回一个java.util.concurrent.Callable,也可以从Spring MVC管理的线程中返回一个值。这样的话,主要的Servlet容器的线程就被释放,可以用来处理其他请求了。Spring MVC会在TaskExecutor的帮助下,在单独的线程中调用Callable对象,并且当Callable对象返回时,这个请求会被分派回Servlet容器,使用这个Callable对象的返回值来恢复处理这个请求。下面是一个例子:
@RequestMapping(method=RequestMethod.POST) public Callable<String> processUpload(final MultipartFile file) { return new Callable<String>() { public String call() throws Exception { // ... return "someView"; } }; }
Controller控制器也可以返回一个DeferredResult实例。这种情况下,那些没有被Spring MVC所管理的返回值也能从任何线程中产生。比如:在响应中,结果可能是,在响应中产生一些类似JMS消息,定时任务等等的外部事件。下面是一个例子:
@RequestMapping("/quotes") @ResponseBody public DeferredResult<String> quotes() { DeferredResult<String> deferredResult = new DeferredResult<String>(); // 在某处保存deferredResult.. return deferredResult; } // 在其他某个线程中… deferredResult.setResult(data);
如果没有关于Servlet 3.0异步请求处理特性的知识,可能比较难理解。下面是关于Servlet3.0基础机制的要点:
通过调用request.startAsync(),能够把ServletRequest放到异步模式中。这样做会导致Servlet或任何Filters(过滤器)退出后,响应还是保持开通状态,来继续完成它的处理过程。
调用request.startAsync()返回的AsyncContext能在整个异步处理过程中使用。例如:它提供了一个方法”dispatch”,这个方法与Servlet API中的forward类似,只是不能在应用里的Servlet容器的线程中,恢复请求的处理过程。
ServletRequest提供对现有DispatcherType的访问,DispatcherType能用来在初始化的请求处理过程,一个异步的dispatch,一个forward,和其他dispatcher(分派器)类型区别开来。
记住了上面的要点,来看看下面的内容--使用Callable来处理异步请求时的事件顺序:
Controller返回一个Callable
Spring MVC开始异步处理过程,并且把Callable上交到TaskExecutor,在一个单独的线程中处理。
DispatcherServlet和所有Filter从Servlet容器中退出,但是,响应还是保持开通状态。
Callable产生了一个结果,并且Spring MVC把该请求分派回Servlet容器,来恢复处理过程。
DispatcherServlet被再次调用,并使用从Callable异步产生的结果来处理恢复的状态。
在DeferredResult中除了它取决于应用中,任何线程产生的异步结果外,它的顺序也是与Callable十分相似的:
Controller返回一个DeferredResult,并保存到它能够访问的内存中的queue或者list中。
Spring MVC开始异步处理过程。
DispatcherServlet和所有配置了的Filter退出该请求的处理的线程,但是响应还是处于开通状态。
该应用中从一些线程中设置了DeferredResult,然后Spring MVC分派该请求回Servlet容器中。
DispatcherServlet被再次调用,并使用异步产生了的结果处理恢复状态。
需要详细了解异步请求处理过程的行为或者了解为何,何时使用它,请参阅这个博客发表的系列文章。
异步请求的异常处理
如果在一个controller方法中,Callable在执行中抛出了错误会怎样?简短版的答案是:与controller方法抛出错误时发生的状况是一样的。它也是使用常规的异常处理机制。加长版答案是:当Callable抛出了异常,SpringMVC把这个Exception当作结果,分派到Servlet容器,这将导致恢复请求处理时,是使用的这个Exception,而不是一个controller方法的返回值。当使用DeferredResult时,你可以选择调用setResult或setErrorResult来处理Exception实例。
拦截异步请求
HandlerInterceptor也可以实现AsyncHandlerInterceptor来实现afterConcurrentHandlingStarted的回调。当异步的处理过程开始时,这个回调代替了postHandle和afterCompletion。
HandlerInterceptor也能注册CallableProcessingInterceptor或DefferedResultProcessingInterceptor来与一个异步请求的生命周期深度结合,例如:处理一个会超时的事件。详见AsyncHandlerInterceptor的javadoc文档。
DefferredResult类也提供如onTimeout(Runnable)和onCompletion(Runnable)的方法。详见DeferredResult的javadoc文档。
当使用Callable时,你也能用WebAsyncTask的实例来封装它,WebAsyncTask也能提供timeout和completion的注册方法。
相关文章推荐
- ruby实现的一个异步文件下载HttpServer实例
- C#异步绑定数据实现方法
- 插件管理框架 for Delphi(一)
- 科学知识:同步、异步、阻塞和非阻塞区别
- 探讨Ajax中同步与异步之间的区别
- 使用CSS框架布局的缺点和优点小结
- C#中异步回调函数用法实例
- 一起动手编写Android图片加载框架
- 基于.NET平台常用的框架和开源程序整理
- C#实现异步GET的方法
- C#异步下载文件
- 列举PHP的Yii 2框架的开发优势
- C#异步执行任务的方法
- 简单实现C#异步操作
- Windows窗体的.Net框架绘图技术实现方法
- 浅谈JavaScript 框架分类
- 使用Promise解决多层异步调用的简单学习心得
- 轻量级javascript 框架Backbone使用指南
- 深入理解JavaScript编程中的同步与异步机制
- javascript实现框架高度随内容改变的方法