异步请求返回DeferredResult,ListenableFuture,CompletionStage原理

// 返回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());
                // 第一次执行,被DeferredResultMethodReturnValueHandler处理,因为方法返回的是DeferredResult
                // 第二次,得到任务的结果之后,就按照普通的请求处理返回值
                this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);{
                    // 如果返回值为空,请求结束
                    if (returnValue == null) {
                        mavContainer.setRequestHandled(true);
                        return;
                    }
                    // 返回结果
                    DeferredResult<?> result;
                    // 如果返回类型为DeferredResult
                    if (returnValue instanceof DeferredResult) {
                        result = (DeferredResult<?>) returnValue;
                    }
                    // 如果是ListenableFuture,进行适配ListenableFuture -> DeferredResult
                    else if (returnValue instanceof ListenableFuture) {
                        result = adaptListenableFuture((ListenableFuture<?>) returnValue);{
                            DeferredResult<Object> result = new DeferredResult<>();
                            // 将ListenableFuture转DeferredResult
                            future.addCallback(new ListenableFutureCallback<Object>() {
                                @Override
                                public void onSuccess(@Nullable Object value) {
                                    result.setResult(value);
                                }
                                @Override
                                public void onFailure(Throwable ex) {
                                    result.setErrorResult(ex);
                                }
                            });
                            return result;
                        }
                    }
                    // 如果是CompletionStage,进行适配CompletionStage -> DeferredResult
                    else if (returnValue instanceof CompletionStage) {
                        result = adaptCompletionStage((CompletionStage<?>) returnValue);{
                            DeferredResult<Object> result = new DeferredResult<>();
                            future.handle((BiFunction<Object, Throwable, Object>) (value, ex) -> {
                                if (ex != null) {
                                    if (ex instanceof CompletionException && ex.getCause() != null) {
                                        ex = ex.getCause();
                                    }
                                    result.setErrorResult(ex);
                                }
                                else {
                                    result.setResult(value);
                                }
                                return null;
                            });
                            return result;
                        }
                    }
                    // 其他的类型,统统抛出异常
                    else {throw new IllegalStateException("Unexpected return value type: " + returnValue);}
                    // 启动任务
                    WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(result, mavContainer);{
                        // 设置超时时间
                        Long timeout = deferredResult.getTimeoutValue();
                        if (timeout != null) {
                            this.asyncWebRequest.setTimeout(timeout);
                        }
                         // 添加拦截器
                        List<DeferredResultProcessingInterceptor> interceptors = new ArrayList<>();
                        interceptors.add(deferredResult.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();
                                    }
                                }
                            };
                        });
                        // 添加DeferredResultProcessingInterceptor类型的拦截器
                        interceptors.addAll(this.deferredResultInterceptors.values());
                        // DeferredResultProcessingInterceptor timeoutDeferredResultInterceptor = new TimeoutDeferredResultProcessingInterceptor();
                        interceptors.add(timeoutDeferredResultInterceptor);
                        // 创建拦截器执行链
                        final DeferredResultInterceptorChain interceptorChain = new DeferredResultInterceptorChain(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(() -> {
                            try {
                                interceptorChain.triggerAfterTimeout(this.asyncWebRequest, deferredResult);
                            }
                            catch (Throwable ex) {
                                setConcurrentResultAndDispatch(ex);
                            }
                        });
                        // 添加处理错误的handler,在AsyncManager中的asyncWebRequest属性中添加
                        this.asyncWebRequest.addErrorHandler(ex -> {
                            if (!this.errorHandlingInProgress) {
                                try {
                                    if (!interceptorChain.triggerAfterError(this.asyncWebRequest, deferredResult, ex)) {
                                        return;
                                    }
                                    deferredResult.setErrorResult(ex);
                                }
                                catch (Throwable interceptorEx) {
                                    setConcurrentResultAndDispatch(interceptorEx);
                                }
                            }
                        });
                        // 添加任务执行完成的Handler,在AsyncManager中的asyncWebRequest属性中添加
                        this.asyncWebRequest.addCompletionHandler(()-> interceptorChain.triggerAfterCompletion(this.asyncWebRequest, deferredResult));
                        // 执行所有interceptor的applyBeforeConcurrentHandling方法
                        interceptorChain.applyBeforeConcurrentHandling(this.asyncWebRequest, deferredResult);
                        // 启动异步任务
                        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 {
                            // 执行所有DeferredResultProcessingInterceptor的applyPreProcess方法
                            interceptorChain.applyPreProcess(this.asyncWebRequest, deferredResult);
                            // 设置结果处理的Handler,内部会加锁,等待结果,下面有源码讲解
                            deferredResult.setResultHandler(result -> {
                                result = interceptorChain.applyPostProcess(this.asyncWebRequest, deferredResult, result);
                                setConcurrentResultAndDispatch(result);
                            });
                            // setResultHandler源码
                            setResultHandler{
                                // 请求过期(超时)
                                if (this.expired) {
                                    return;
                                }
                                // 返回结果
                                Object resultToHandle;
                                // 加锁
                                synchronized (this) {
                                    // 再次校验当前请求有没有过期(超时)
                                    if (this.expired) {
                                        return;
                                    }
                                    // 保存结果
                                    // 默认的结果为RESULT_NONE,是this.result的默认值
                                    resultToHandle = this.result;
                                    // 如果resultToHandle == RESULT_NONE表示当前结果还是默认值,
                                    if (resultToHandle == RESULT_NONE) {
                                        // 当前执行的resultHandler,因为resultHandler还没有开始执行,先要保存下来
                                        this.resultHandler = resultHandler;
                                        return;
                                    }
                                }
                                //上面已经加锁了,如果我们到达这里,说明我们的结果已经设置了resultToHandle == RESULT_NONE此时不成立
                                // 避免Servlet容器锁的死锁
                                try {
                                    // 开始调用resultHandler,执行处理结果
                                    resultHandler.handleResult(resultToHandle);{
                                        // 执行拦截器的applyPostProcess方法
                                        result = interceptorChain.applyPostProcess(this.asyncWebRequest, deferredResult, result);
                                        // 设置响应结果并且再次发送请求
                                        setConcurrentResultAndDispatch(result);{
                                            synchronized (WebAsyncManager.this) {
                                                // 如果concurrentResult不等于表示结果已经设置过了
                                                if (this.concurrentResult != RESULT_NONE) {
                                                    return;
                                                }
                                                // 设置最终结果
                                                this.concurrentResult = result;
                                                // 设置是否发生了错误
                                                this.errorHandlingInProgress = (result instanceof Throwable);
                                            }
                                            // 判断异步任务是否完成,如果是异步返回值,都会调用this.asyncWebRequest.dispatch();重新分发请求
                                            // org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onComplete中设置的这个标识为true
                                            // 只有当前异步任务执行完毕的时候,设置了结果,tomcat自动会回调监听器StandardServletAsyncWebRequest.onComplete中设置的这个标识为true
                                            // 异步结果处理都是在上面第二次处理请求的时候处理的,上面有代码 if(asyncManager.hasConcurrentResult()) {xxx}
                                            if (this.asyncWebRequest.isAsyncComplete()) {
                                                return;
                                            }
                                            // 重新向Tomcat发送相同的请求,并且,请求对象不在是RequestFacade对象,而是org.apache.catalina.core.ApplicationHttpRequest对象
                                            // 内部封装了上一次请求的RequestFacade对象,已经分发类型为ASYNC
                                            this.asyncWebRequest.dispatch();
                                        }
                                    }
                                }
                                catch (Throwable ex) {
                                    logger.debug("Failed to process async result", ex);
                                }
                            }

                        }
                        catch (Throwable ex) {
                            setConcurrentResultAndDispatch(ex);
                        }
                    }
                }
            }
            // 开启了异步Handler处理,就不往下执行了
            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }
        }
    }
}
// 对于handler方法,开启了异步Handler处理,就不往下执行了,如果是异步任务,因为任务还没执行完成
if (asyncManager.isConcurrentHandlingStarted()) {
	return;
}

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值