跳至主要內容

24. 异步请求管理器 WebAsyncManager 初始化

安图新大约 3 分钟

24. 异步请求管理器 WebAsyncManager 初始化

前言

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 的初始化,以及参数的配置。