// 返回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;
}
异步请求返回DeferredResult,ListenableFuture,CompletionStage原理
于 2024-01-20 23:13:04 首次发布