前言
Springmvc的异步执行请求是有异步管理器WebAsyncManager来控制的。
一、WebAsyncManager初始化
1、在请求到来时,会调用DispatcherServlet的doService方法,在调用该方法之前会进入FrameworkServlet的processRequest方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
//创建WebAsyncManager
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
//设置拦截器
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
2、getAsyncManager( )方法
public static WebAsyncManager getAsyncManager(ServletRequest servletRequest) {
WebAsyncManager asyncManager = null;
//public static final String WEB_ASYNC_MANAGER_ATTRIBUTE = WebAsyncManager.class.getName() + ".WEB_ASYNC_MANAGER";
Object asyncManagerAttr = servletRequest.getAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE);
if (asyncManagerAttr instanceof WebAsyncManager) {
asyncManager = (WebAsyncManager) asyncManagerAttr;
}
if (asyncManager == null) {
//为空时,创建一个新的WebAsyncManager
asyncManager = new WebAsyncManager();
//设置到request的Attribute中
servletRequest.setAttribute(WEB_ASYNC_MANAGER_ATTRIBUTE, asyncManager);
}
return asyncManager;
}
二、参数的初始化
1、在请求过程中,会经过RequestMappingHandlerAdapter的invokeHandlerMethod( )方法,方法中会适配异步管理器的超时时间、线程池、拦截器等
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
//创建异步request StandardServletAsyncWebRequest
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
//设置超时时间
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
//获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
//设置taskExecutor
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
//设置Callable的拦截器
asyncManager.registerCallableInterceptors(this.callableInterceptors);
//设置DeferredResult的拦截器
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
//异步执行,已经解析出结果,发生在该请求接口执行完后的第二次请求结果,获取执行结果
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer);
//如果是异步执行,返回null
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
三、自定义参数
对异步管理器的超时时间、线程池、拦截器等进行自定义
1、线程池的配置
@Configuration
@EnableAsync
public class ThreadPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
int processors = Runtime.getRuntime().availableProcessors();
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(processors);
executor.setMaxPoolSize(processors * 2);
executor.setQueueCapacity(10000);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
return executor;
}
}
2、参数的配置
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AsyncTaskExecutor taskExecutor;
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
//设置默认超时时间
configurer.setDefaultTimeout(20000);
//设置线程池
configurer.setTaskExecutor(taskExecutor);
//设置拦截器
// configurer.registerCallableInterceptors();
// configurer.registerDeferredResultInterceptors();
}
}
3、参数的解析
参数最终在RequestMappingHandlerAdapter中设置到异步管理器中,那下面就看一下参数是怎么设置到RequestMappingHandlerAdapter中的
1、 RequestMappingHandlerAdapter的初始化过程;
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setContentNegotiationManager(contentNegotiationManager);
adapter.setMessageConverters(getMessageConverters());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
adapter.setCustomArgumentResolvers(getArgumentResolvers());
adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
//获取AsyncSupportConfigurer
AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
if (configurer.getTaskExecutor() != null) {
//设置线程池
adapter.setTaskExecutor(configurer.getTaskExecutor());
}
if (configurer.getTimeout() != null) {
//设置超时时间
adapter.setAsyncRequestTimeout(configurer.getTimeout());
}
//设置拦截器
adapter.setCallableInterceptors(configurer.getCallableInterceptors());
adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
return adapter;
}
2、 getAsyncSupportConfigurer();
WebMvcConfigurationSupport.java
protected AsyncSupportConfigurer getAsyncSupportConfigurer() {
if (this.asyncSupportConfigurer == null) {
this.asyncSupportConfigurer = new AsyncSupportConfigurer();
//配置
configureAsyncSupport(this.asyncSupportConfigurer);
}
return this.asyncSupportConfigurer;
}
3、 configureAsyncSupport();
DelegatingWebMvcConfiguration.java
protected void configureAsyncSupport(AsyncSupportConfigurer configurer) {
this.configurers.configureAsyncSupport(configurer);
}
WebMvcConfigurerComposite.java
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureAsyncSupport(configurer);
}
}
这里的delegates是实现WebMvcConfigurer的类
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
//这里将WebMvcConfigurer缓存到delegates中
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
}
总结
本文主要介绍WebAsyncManager的初始化,以及参数的配置。