1.servlet会请求两次
一个是public void handle(HttpChannel channel);
另一个是public void handleAsync(HttpChannel channel)
第一次是在httpConnection中通过onFillable()方法调用HttpChannel的handle()方法(正常请求都是通过此执行的)
第二次在httpchannelState中的dispatch方法(添加httpChannel任务到线程池中,会再次调用handle()方法)执行的
2.正常流程
(1)第一次servlet调用deferredResultMethodReturnValueHandler的handleReturnValue()方法时,先设置standardServletAsyncWebRequest的startAsync()方法(其中执行asyncContext.addListener(this),添加处理成功,处理失败,处理超时的逻辑),同时设置deferredResult的deferredResultHandler的处理器。
(2)异步 deferredResult执行完setResult方法后通过调用deferredResultHandler才执行standardServletAsyncWebRequest中的dispatch,最终执行httpChannelState中的dispatch方法,才会再次发起servlet请求
3.超时设置的原理
httpChannelState中unhandle()方法在async状态设为started(第一次startAsync()方法)后,会执行scheduler.schedule(_event,_timeoutMs,TimeUnit.MILLISECONDS),延时添加到调度线程池中,如果这个run方法执行了,则代表超时了,正常执行后这个task要取消掉。
4.两次servlet的请求的区别
1.第一次请求与第二次请求是同一个reqeust,共用一个webAsyncManager,第一次请求时设置了concurrentResutl的值,第二次时取到了这个结果, 不会再进入controller方法。
2.第一次请求调用原始方法能过反射的方式,执行得到结果,第二次请求是重新包装了一个新的类concurrentResultHandlerMethod,原样得到结果
3.第一次handlerMethodReturnValueHandler是deferredResultMethodReturnValueHandler
第二次handlerMethodReturnValueHandler根据deferredResult<T>中T类型匹配
注:由于涉及多线程,所以DeferredResult中要用到volatile
5.正常执行与超时执行
正常执行与超时执行都会调用两次servlet,区别是:
(1)正常执行的在异步线程中设置DeferredResult中的result是正常的值
(2) 超时执行在schedule中设置DeferredResult中的result是AsyncRequestTimeoutException
这样在第二次servlet会不同,正常执行的第二次servlet是原样返回异步线程中设置的值,超时执行则抛出异常(ConcurrentResultHandlerMethod)