跳至主要內容

8. RequestMappingHandlerAdapter

安图新大约 4 分钟

8. RequestMappingHandlerAdapter

一、实例化

WebMvcConfigurationSupport.java

@Bean
	public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcValidator") Validator validator) {



		RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
		adapter.setContentNegotiationManager(contentNegotiationManager);
		//WebMvcConfigurer接口实现类的configureMessageConverters,消息转换器
		adapter.setMessageConverters(getMessageConverters());
		adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
		//WebMvcConfigurer接口实现类的addArgumentResolvers,定制参数解析器
		adapter.setCustomArgumentResolvers(getArgumentResolvers());
		//WebMvcConfigurer接口实现类的addReturnValueHandlers,定制返回值解析器
		adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

		if (jackson2Present) {


			adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
			adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
		}

		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;
	}

二、初始化

(1)afterPropertiesSet( )

@Override
	public void afterPropertiesSet() {


		// Do this first, it may add ResponseBody advice beans
		//初始化@ControllerAdvice、@RestControllerAdvice标识的类
		initControllerAdviceCache();

		//参数解析器
		if (this.argumentResolvers == null) {


			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		//initBinder参数解析器
		if (this.initBinderArgumentResolvers == null) {


			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		//返回值处理器
		if (this.returnValueHandlers == null) {


			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

(2)initControllerAdviceCache( )

private void initControllerAdviceCache() {


		if (getApplicationContext() == null) {


			return;
		}

		//获取@ControllerAdvice的Bean
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

		List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();

		for (ControllerAdviceBean adviceBean : adviceBeans) {


			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {


				throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
			}
			//获取@ModelAttribute注解的方法
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {


				this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
			}
			//获取@InitBinder注解的方法
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {


				this.initBinderAdviceCache.put(adviceBean, binderMethods);
			}
			//是否实现了RequestBodyAdvice或ResponseBodyAdvice接口
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {


				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {


			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}

		if (logger.isDebugEnabled()) {


			int modelSize = this.modelAttributeAdviceCache.size();
			int binderSize = this.initBinderAdviceCache.size();
			int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
			int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
			if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {


				logger.debug("ControllerAdvice beans: none");
			}
			else {


				logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
						" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
			}
		}
	}

三、获取 Adapter

(1)DispatcherServlet.getHandlerAdapter( )

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {


		if (this.handlerAdapters != null) {


			for (HandlerAdapter adapter : this.handlerAdapters) {


				//遍历所有适配器,这里分析RequestMappingHandlerAdapter
				if (adapter.supports(handler)) {


					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

(2)RequestMappingHandlerAdapter.supports( )

public final boolean supports(Object handler) {


		//是HandlerMethod,并且调用子类supportsInternal,RequestMappingHandlerAdapter的supportsInternal方法返回true
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

protected boolean supportsInternal(HandlerMethod handlerMethod) {


		return true;
	}

四、执行 handler

接下来调用适配器的 handler 方法

(1)AbstractHandlerMethodAdapter.handle( )

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {


		//回调子类的RequestMappingHandlerAdapter的handleInternal( )
		return handleInternal(request, response, (HandlerMethod) handler);
	}

(2)RequestMappingHandlerAdapter.handleInternal( )

返回 ModelAndView

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {



		ModelAndView mav;
		//检查方法是否支持以及是否需要session
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		//同步
		if (this.synchronizeOnSession) {


			HttpSession session = request.getSession(false);
			if (session != null) {


				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {


					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {


				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {


			// No synchronization on session demanded at all...
			//异步,返回ModelAndView
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {


			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {


				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {


				prepareResponse(response);
			}
		}

		return mav;
	}

(3)invokeHandlerMethod( )

	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {



		//包装请求和响应
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {


			//处理initBinderMethod
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			//包装handlerMethod
			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);

			//ModelAndView容器
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			//异步请求处理
			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);

			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			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);
			}

			//调用目标handler
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {


				return null;
			}

			//执行完获取ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {


			webRequest.requestCompleted();
		}
	}

(4)invokeAndHandle( )

ServletInvocableHandlerMethod.java

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {



		//执行invokeForRequest
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {


			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {


				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {


			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {


			//调用返回值处理器处理结果
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {


			if (logger.isTraceEnabled()) {


				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}

(5)invokeForRequest( )

InvocableHandlerMethod.java

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {



		//解析参数值
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {


			logger.trace("Arguments: " + Arrays.toString(args));
		}
		//执行目标方法
		return doInvoke(args);
	}

(6)getMethodArgumentValues( )

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {



		//获取方法参数
		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {


			return EMPTY_ARGS;
		}

		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {


			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {


				continue;
			}
			//参数解析器支持该参数
			if (!this.resolvers.supportsParameter(parameter)) {


				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
			}
			try {


				//解析出参数
				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
			}
			catch (Exception ex) {


				// Leave stack trace for later, exception may actually be resolved and handled...
				if (logger.isDebugEnabled()) {


					String exMsg = ex.getMessage();
					if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {


						logger.debug(formatArgumentError(parameter, exMsg));
					}
				}
				throw ex;
			}
		}
		return args;
	}

解析完参数后,进行方法的调用

(7)doInvoke( )

protected Object doInvoke(Object... args) throws Exception {


		Method method = getBridgedMethod();
		ReflectionUtils.makeAccessible(method);
		try {


			if (KotlinDetector.isSuspendingFunction(method)) {


				return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
			}
			//通过反射调用
			return method.invoke(getBean(), args);
		}

...
}

目标方法执行完毕,进入结果的处理

(8)handleReturnValue( )

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {



		//找出合适的处理结果的handler
		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
		if (handler == null) {


			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
		}
		//处理结果
		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
	}

处理完结果,处理 ModelAndView

(9)getModelAndView( )

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {



		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {


			return null;
		}
		ModelMap model = mavContainer.getModel();
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {


			mav.setView((View) mavContainer.getView());
		}
		if (model instanceof RedirectAttributes) {


			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {


				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		return mav;
	}

}