异步请求返回Callable和AsyncWebTask原理

// 返回callable
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());{
     return handleInternal(request, response, (HandlerMethod) handler);{
       return mav = invokeHandlerMethod(request, response, handlerMethod);{
            // 获取异步请求对象
            AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
            // 设置超时时间
            asyncWebRequest.setTimeout(this.asyncRequestTimeout);
            // 获取异步管理器
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);{
                // 当请求对象是同一个的话,获取的WebAsyncManager就是同一个
                // 在处理第一次处理请求的异步返回值的时候,就将WEB_ASYNC_MANAGER_ATTRIBUTE存进入了
                // 然后当Tomcat再次分发请求的时候,携带的request是包装之后的request,org.apache.catalina.core.ApplicationHttpRequest,里面有一个request对象
                // 就是包装的上次的请求对象RequestFacade
                // 通过这个request请求对象,也能获取到WEB_ASYNC_MANAGER_ATTRIBUTE,因为这个获取getAttribute实在tomcat内部做的
                // 所以前后两次的request对象可以理解为同一个
                WebAsyncManager asyncManager = null;
                Object asyncManagerAttr = servletRequest.getAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE);
                if (asyncManagerAttr instanceof WebAsyncManager) {
                    asyncManager = (WebAsyncManager) asyncManagerAttr;
                }
                // 没有就创建,所以,同一个请求只有一个WebAsyncManager
                if (asyncManager == null) {
                    asyncManager = new WebAsyncManager();
                    servletRequest.setAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE, asyncManager);
                }
                return asyncManager;
            }
            // 设置线程池
            asyncManager.setTaskExecutor(this.taskExecutor);
            // 设置AsyncWebRequest对象
            asyncManager.setAsyncWebRequest(asyncWebRequest);
            // 注册这两个返回值的拦截器
            asyncManager.registerCallableInterceptors(this.callableInterceptors);
            asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
            // 判断是否已经有并发执行的结果,第一次执行肯定没有,但是第二次执行肯定有
            // 因为这个异步任务执行完成的时候,设置了结果,才进行了再次发送请求操作
            // 这就是为什么在handler方法,invokeHandlerMethod等等多个方法都会判断是否是异步操作,如果是异步操作就立刻return
            // 就是因为执行异步任务会处理两次请求,第一次是正常执行,开启异步任务,第二次是获取异步任务结果,返回响应
            if (asyncManager.hasConcurrentResult()) {
                // 获取结果
                Object result = asyncManager.getConcurrentResult();
                // 获取到上次请求的mavContainer
                mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
                // 清空执行结果
                asyncManager.clearConcurrentResult();
                // 包装成ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod
                invocableMethod = invocableMethod.wrapConcurrentResult(result);{
                    // ConcurrentResultHandlerMethod是一个Handler,内部包含Handler处理功能的Bean,和目标方法
                    // 所以,它将handler设置为Callable对象,方法是Callable的call方法
                    super((Callable<Object>) () -> {
                        if (result instanceof Exception) {
                            throw (Exception) result;
                        }
                        else if (result instanceof Throwable) {
                            throw new NestedServletException("Async processing failed", (Throwable) result);
                        }
                        return result;
                    }, CALLABLE_METHOD);
                    // 设置返回值处理器,因为拿到结果还需要处理返回值
                    if (ServletInvocableHandlerMethod.this.returnValueHandlers != null) {
                        setHandlerMethodReturnValueHandlers(ServletInvocableHandlerMethod.this.returnValueHandlers);
                    }
                    this.returnType = returnType;
                }
            }
            // 第一次执行方法/或者异步返回值再次执行方法
            invocableMethod.invokeAndHandle(webRequest, mavContainer){;
                // 执行目标方法,得到返回结果
                Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
                // 使用返回值处理器处理,其中就包装在HandlerAdapter中添加的两个
                // 	handlers.add(new CallableMethodReturnValueHandler());
                //  handlers.add(new DeferredResultMethodReturnValueHandler());
                // 第一次执行,被CallableMethodReturnValueHandler处理,因为方法返回的实Callable
                // 第二次,得到任务的结果之后,就按照普通的请求处理返回值
                this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);{
                    // 如果返回值为空,请求结束
                    if (returnValue == null) {
                        mavContainer.setRequestHandled(true);
                        return;
                    }
                    // 强转为callable
                    Callable<?> callable = (Callable<?>) returnValue;
                    // 使用异步管理器启动异步任务
                    // 所以,最终会将callable包装成WebAsyncTask对象,当返回结果是WebAsyncTask的时候,逻辑基本一样
                    // 使用的是AsyncTaskMethodReturnValueHandler的handleValue方法
                    // 也是调用 startCallableProcessing(new WebAsyncTask(callable), processingContext);启动
                    WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer);{
                        startCallableProcessing(new WebAsyncTask(callable), processingContext);{
                            Long timeout = webAsyncTask.getTimeout();
                            // 设置超时时间
                            if (timeout != null) {
                                this.asyncWebRequest.setTimeout(timeout);
                            }
                            // 获取线程池,如果没有,打印警告日志,代码没展示
                            AsyncTaskExecutor executor = webAsyncTask.getExecutor();
                            if (executor != null) {
                                this.taskExecutor = executor;
                            }
                            // 添加拦截器
                            List<CallableProcessingInterceptor> interceptors = new ArrayList<>();
                            interceptors.add(webAsyncTask.getInterceptor());{
                                return new CallableProcessingInterceptor() {
                                    @Override
                                    public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception {
                                        return (timeoutCallback != null ? timeoutCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
                                    }
                                    @Override
                                    public <T> Object handleError(NativeWebRequest request, Callable<T> task, Throwable t) throws Exception {
                                        return (errorCallback != null ? errorCallback.call() : CallableProcessingInterceptor.RESULT_NONE);
                                    }
                                    @Override
                                    public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
                                        if (completionCallback != null) {
                                            completionCallback.run();
                                        }
                                    }
                                };
                            }
                            // asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
                            // org.springframework.web.servlet.FrameworkServlet.RequestBindingInterceptor
                            interceptors.addAll(this.callableInterceptors.values());
                            // CallableProcessingInterceptor timeoutCallableInterceptor = new TimeoutCallableProcessingInterceptor();
                            interceptors.add(timeoutCallableInterceptor);
                            // 获取任务
                            final Callable<?> callable = webAsyncTask.getCallable();
                            // 创建拦截器链
                            final CallableInterceptorChain interceptorChain = new CallableInterceptorChain(interceptors);

                            // 下面三个Handler,都是添加到StandardServletAsyncWebRequest中,而StandardServletAsyncWebRequest是一个AsyncListener监听器
                            // 当任务执行的时候,如果发布AsyncEvent事件,会被StandardServletAsyncWebRequest捕捉,指定对应的回调
                            // 在执行为完毕的时候,Tomcat内部会发布这个事件
                            // 执行org.apache.catalina.core.AsyncContextImpl.fireOnComplete的方法,最终会调用到下面类中对应的回调方法
                            //  org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onComplete
                            // 添加超时的handler,在AsyncManager中的asyncWebRequest属性中添加
                            // this.timeoutHandlers.add(timeoutHandler);
                            this.asyncWebRequest.addTimeoutHandler(() -> {
                                Object result = interceptorChain.triggerAfterTimeout(this.asyncWebRequest, callable);
                                if (result != CallableProcessingInterceptor.RESULT_NONE) {
                                    setConcurrentResultAndDispatch(result);
                                }
                            });
                            // 添加处理错误的handler,在AsyncManager中的asyncWebRequest属性中添加
                            this.asyncWebRequest.addErrorHandler(ex -> {
                                if (!this.errorHandlingInProgress) {
                                    Object result = interceptorChain.triggerAfterError(this.asyncWebRequest, callable, ex);
                                    result = (result != CallableProcessingInterceptor.RESULT_NONE ? result : ex);
                                    setConcurrentResultAndDispatch(result);
                                }
                            });

                            // 添加任务执行完成的Handler,在AsyncManager中的asyncWebRequest属性中添加
                            this.asyncWebRequest.addCompletionHandler(() -> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, callable));
                            // 执行所有CallableProcessingInterceptor interceptor的applyBeforeConcurrentHandling方法
                            interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, callable);
                            // 启动异步任务
                            startAsyncProcessing(processingContext);{
                                synchronized (WebAsyncManager.this) {
                                    // 标注结果为固定值
                                    this.concurrentResult = RESULT_NONE;
                                    this.concurrentResultContext = processingContext;
                                    // 未发生错误
                                    this.errorHandlingInProgress = false;
                                }
                                // 开启任务
                                this.asyncWebRequest.startAsync();{
                                    // 调用Tomcat的开启异步任务方法
                                    this.asyncContext = getRequest().startAsync(getRequest(), getResponse());
                                    // 添加异步监听器,就是当前类StandardServletAsyncWebRequest,他是一个AsyncListener
                                    // 有void onComplete(AsyncEvent event),void onTimeout(AsyncEvent event),void onError(AsyncEvent event)回调
                                    this.asyncContext.addListener(this);
                                    // 如果还有超时时间
                                    if (this.timeout != null) {
                                        // 设置超时时间
                                        this.asyncContext.setTimeout(this.timeout);
                                    }
                                }
                            }
                            try {
                                // 使用线程池执行任务
                                Future<?> future = this.taskExecutor.submit(() -> {
                                    Object result = null;
                                    try {
                                        // 执行拦截器中applyPreProcess方法
                                        interceptorChain.applyPreProcess(this.asyncWebRequest, callable);
                                        // 任务执行
                                        result = callable.call();
                                    }
                                    catch (Throwable ex) {
                                        result = ex;
                                    }
                                    finally {
                                        // 执行拦截器的的applyPostProcess
                                        result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, result);
                                    }
                                    // 设置并发结果
                                    setConcurrentResultAndDispatch(result);{
                                        synchronized (WebAsyncManager.this) {
                                            // 如果concurrentResult不等于表示结果已经设置过了
                                            if (this.concurrentResult != RESULT_NONE) {
                                                return;
                                            }
                                            // 设置最终结果
                                            this.concurrentResult = result;
                                            // 设置是否发生了错误
                                            this.errorHandlingInProgress = (result instanceof Throwable);
                                        }
                                        // 判断异步任务是否完成
                                        if (this.asyncWebRequest.isAsyncComplete()) {
                                            return;
                                        }
                                        // 重新向Tomcat发送相同的请求,并且,请求对象不在是RequestFacade对象,而是org.apache.catalina.core.ApplicationHttpRequest对象
                                        // 内部封装了上一次请求的RequestFacade对象,已经分发类型为ASYNC
                                        this.asyncWebRequest.dispatch();
                                    }
                                });
                                // 保存future,因为到时候拦截器可能会取消任务,例如超时的时候
                                interceptorChain.setTaskFuture(future);
                            }
                            catch (RejectedExecutionException ex) {
                                // 执行拦截器的applyPostProcess方法
                                Object result = interceptorChain.applyPostProcess(this.asyncWebRequest, callable, ex);
                                // 设置执行结果和重新发送同步请求
                                setConcurrentResultAndDispatch(result);
                                throw ex;
                            }
                        }
                    }
                }
            }
            // 开启了异步Handler处理,就不往下执行了
            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }
        }
    }
}
// 对于handler方法,开启了异步Handler处理,就不往下执行了,如果是异步任务,因为任务还没执行完成
if (asyncManager.isConcurrentHandlingStarted()) {
	return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值