Spring-webmvc

异步请求

2019-07-09  本文已影响0人  xzz4632

1. 启用异步请求

// 添加到<servlet>中
<async-supported>true</async-supported>

// 添加到filter-mapping中
<dispatcher>ASYNC</dispatcher>

2. 实现方式

2.1 DeferredResult

使用DeferredResult包装返回值, 这种形式用其他线程来处理请求并生成结果.

@RequestMapping("/deferred")
public DeferredResult<String> deferred() {
    DeferredResult<String> result = new DeferredResult<>();
    // 可以创建线程去处理请求(处理结果设置在result对象中)
    return result;
}
2.2 Callable

使用Callable包装返回值, 这种方式可以调用TaskExecutor处理请求.

    @RequestMapping("/call")
    public Callable<String> call() {
        return new Callable<String>() {
            @Override
            public String call() throws Exception {     
                return "callable";
            }   
        };
    }

3. 工作过程

3.1 ServletRequest的工作过程
request.startAsync();
request.getAsyncContext();
request.getDispatcherType().
3.2 DeferredResult的工作过程

注: 使用DeferredResult时,可以选择调用setResult还是setErrorResult。在这两种情况下,Spring MVC都将请求发回Servlet容器以完成处理。然后将其视为控制器方法返回给定值或产生给定异常。然后通过常规异常处理机制进行处理(例如,调用@ExceptionHandler方法)。

3.3 Callable的工作过程

4. 异步请求拦截器

4.1 AsyncHandlerInterceptor

实现这个接口, 接口中定义了方法afterConcurrentHandlingStarted(), 异步请求开始后调用的回调方法.

当处理程序启动异步请求时,DispatcherServlet将退出,不会调用postHandleafterCompletion,因为请求处理的结果(例如ModelAndView)可能还没有准备好,并且将从另一个线程并发生成。此时, 将由afterConcurrentHandlingStarted()方法来代替它们. 做一些线程资源释放工作.
当异步处理完成之后, 请求会被发回容器进行进一步的处理, 此时DispatcherServlet会调用preHandle, postHandle, afterCompletion方法, 拦截器通过检查请求的DispatcherTypeREQUEST还是ASYNC来区分请求是初始请求还是异步处理后的请求.
注意:当异步请求超时, 则请求不会被再次分发给容器进行处理, 因此拦截器方法就不会被调用.这可以通过WebAsyncManagerregisterCallbackInterceptorregisterDeferredResultInterceptor方法注册拦截器, 这可以保证无论异步请求是否启动, 都可以执行preHandle操作.

上一篇 下一篇

猜你喜欢

热点阅读