Published on

Spring MVC处理器适配器的源码详解

Authors
  • avatar
    Name
    OiPunk
    Twitter

处理器适配器的详细处理过程

​ 当把需要的处理器和适配器找到之后,下面就开始执行具体的处理过程了,通过下述代码进行调用:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

找到RequestMappingHandlerAdapter的类中

@Override	protected ModelAndView handleInternal(HttpServletRequest request,			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {		// 先声明ModelAndView结果		ModelAndView mav;        // 检查请求是否支持,1、通过supportedMethods方法判断是否包含请求方法,2、检查请求中是否包含session		checkRequest(request);		// Execute invokeHandlerMethod in synchronized block if required.        // 处理时是否对session加锁,默认为false		if (this.synchronizeOnSession) {            // 获取session对象			HttpSession session = request.getSession(false);            // 对session是否为空做判断,如果不等于空			if (session != null) {                // 获取session中锁对象				Object mutex = WebUtils.getSessionMutex(session);                // 加锁后执行调用处理器方法逻辑				synchronized (mutex) {					mav = invokeHandlerMethod(request, response, handlerMethod);				}			}			else {				// No HttpSession available -> no mutex necessary                // 没有session,则忽略加所,直接执行调用处理器方法逻辑				mav = invokeHandlerMethod(request, response, handlerMethod);			}		}		else {			// No synchronization on session demanded at all...			mav = invokeHandlerMethod(request, response, handlerMethod);		}		// 如果响应结果不包含缓存控制头		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {            // 如果该处理器方法包含sessionAttribute			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {				// 应哟个sessionAttributes的缓存策略                applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);			}			else {                //不包含SessionAttribute,准备请求。内部逻辑应用配置的缓存策略,本适配器默认没有缓存策略,故所有请求都不返回缓存响应头				prepareResponse(response);			}		}		// 返回结果		return mav;	}

1、mav = invokeHandlerMethod(request, response, handlerMethod);

@Nullable	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {		// 把请求和响应封装为一个ServletWebRequest对象		ServletWebRequest webRequest = new ServletWebRequest(request, response);		try {            // 创建WebDataBinderFactory工厂,该工厂用于获取处理器方法对应的WebDataBinder组件			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);            // 获取当前处理器方法对应的Model工厂,该工厂用于获取处理器方法对应的model			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);			// 创建一个Servlet下可调用处理器的方法,内部创建了一个ServletInvocableHandlerMethod对象			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);            //设置参数解析器			if (this.argumentResolvers != null) {				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);			}            // 设置返回值处理器			if (this.returnValueHandlers != null) {				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);			}            // 设置DataBinder工厂			invocableMethod.setDataBinderFactory(binderFactory);            // 设置参数名获取器,用于获取方法上的参数名			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);			// 创建用于处理过程中使用的ModelAndView容器			ModelAndViewContainer mavContainer = new ModelAndViewContainer();            // 向MV容器中添加FlashMap的属性			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));            // 初始化Model,包含调用Model相关的初始化方法,如ModelAttribute注解标记的方法			modelFactory.initModel(webRequest, mavContainer, invocableMethod);			//在重定向时忽略默认的Model属性值,只考虑重定向Model的属性值,默认为true	         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);			}			// 调用处理器方法并处理返回值			invocableMethod.invokeAndHandle(webRequest, mavContainer);			if (asyncManager.isConcurrentHandlingStarted()) {				return null;			}			// 获取MV结果			return getModelAndView(mavContainer, modelFactory, webRequest);		}		finally {            // 标记请求完成			webRequest.requestCompleted();		}	}
1、WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {    	// 获取处理器方法所在的Bean类型		Class handlerType = handlerMethod.getBeanType();    	// 从InitBinder缓存中获取当前处理器类型标记了@InitBinder注释的方法		Set methods = this.initBinderCache.get(handlerType);    	// 如果为空,说明缓存中没有,进入获取逻辑		if (methods == null) {            // 找到所有标记了@InitBinder的方法			methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);			// 添加到缓存中            this.initBinderCache.put(handlerType, methods);		}    	// 保存全部标记了@InitBinder方法的结果列表		List initBinderMethods = new ArrayList<>();		// Global methods first    	// 遍历全局InitBinder增强器缓存		this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {            //  判断是否能够应用到当前处理器中,判断依据是@ControllerAdvice			if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {				Object bean = controllerAdviceBean.resolveBean();				for (Method method : methodSet) {					initBinderMethods.add(createInitBinderMethod(bean, method));				}			}		});    	// 添加处理器方法所在Bean的@InitBinder方法		for (Method method : methods) {			Object bean = handlerMethod.getBean();            // 把Bean和方法封装为InvocableHandlerMethod			initBinderMethods.add(createInitBinderMethod(bean, method));		}    	// 把InitBinder方法参数列表作为参数,创建WebDataBinder工厂		return createDataBinderFactory(initBinderMethods);	}
2、ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {    	// 获取SessionAttributes的处理器,用于处理处理器Bean类型上标记的@SessionAttributes注解		SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);    	// 获取处理器Bean类型		Class handlerType = handlerMethod.getBeanType();    	// 从ModelAttribute缓存中获取Bean类型对应的@ModelAttribute标记的方法		Set methods = this.modelAttributeCache.get(handlerType);		if (methods == null) {            // 若缓存中没有,则进入获取逻辑,获取处理器类型中标记了@ModelAttribute注解且未标记@RequestMapping注解的方法,作为ModelAttribute方法			methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);            // 加入缓存			this.modelAttributeCache.put(handlerType, methods);		}    	// 创建一个列表,用于保存@ModelAttribute注解标注方法的InvocableHandlerMethod,可以调用封装		List attrMethods = new ArrayList<>();		// Global methods first		this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {            // 通过@ControllerAdvice的属性进行过滤,判断是否可被应哟个到当前处理器Bean中			if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {                // 解析处理器增强Bean为实例				Object bean = controllerAdviceBean.resolveBean();				for (Method method : methodSet) {                    //遍历对应的方法集合,创建ModelAttribute可调用方法,添加到结果列表中					attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));				}			}		});    	//全局@ModelAttribute方法添加完成之后,添加当前处理器Bean中的@ModelAttribute方法		for (Method method : methods) {			Object bean = handlerMethod.getBean();			attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));		}    	// 返回Model工厂实例,封装全部@ModelAttribute的可调用方法		return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);	}
3、ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {    	//创建了一个新的对象		return new ServletInvocableHandlerMethod(handlerMethod);	}
4、modelFactory.initModel(webRequest, mavContainer, invocableMethod);
public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod)			throws Exception {		// 使用SEssionAttribute处理器,先从Session中获取@SessionAttributes注解声明的session属性		Map sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);    	// 把@SessionAttributes声明的session属性全部合并到ModelAndView容器中		container.mergeAttributes(sessionAttributes);    	// 调用@ModelArrtibute注解标记的方法,把方法返回值放入ModelAndView容器的Model中		invokeModelAttributeMethods(request, container);		// 遍历返回的name列表		for (String name : findSessionAttributeArguments(handlerMethod)) {            // 如果MV容器中不包含name属性,则从session中获取该属性,添加到容器中			if (!container.containsAttribute(name)) {				Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);				if (value == null) {					throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);				}				container.addAttribute(name, value);			}		}	}-----------------------------------------------------------------------------------------private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)			throws Exception {		// 遍历全部模型属性方法,直到为空		while (!this.modelMethods.isEmpty()) {            // 获取当前遍历的可调用模型属性方法			InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();            // 检查该方法上是否存在@ModelAttribute注解			ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);			Assert.state(ann != null, "No ModelAttribute annotation");            // 如果当前容器中已经包含了模型属性方法声明的模型名,则不覆盖现有属性			if (container.containsAttribute(ann.name())) {                // 如果注解标记了binding=false,则把这个属性名添加到容器的不绑定列表中,用于在参数绑定时忽略此模型属性的绑定				if (!ann.binding()) {					container.setBindingDisabled(ann.name());				}				continue;			}			// 根据请求执行模型属性方法,获取模型属性方法的返回值			Object returnValue = modelMethod.invokeForRequest(request, container);            // 如果方法声明的返回值类型不是void,则继续处理这个返回值			if (!modelMethod.isVoid()){                // 根据返回值与返回类型获取返回的属性名,一般是从方法注解@ModelAttribute的name属性中获取该属性名				String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());                // 判断是否声明了binding=false				if (!ann.binding()) {					container.setBindingDisabled(returnValueName);				}                // 再次判断容器的Model中是否包含此模型属性				if (!container.containsAttribute(returnValueName)) {                    // 不包含,则把模型属性名与对应的返回值添加到容器中					container.addAttribute(returnValueName, returnValue);				}			}		}	}
5、invocableMethod.invokeAndHandle(webRequest, mavContainer);
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,			Object... providedArgs) throws Exception {		// 执行调用方法获取处理器方法的返回值,内部包含参数解析		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;		}	}-----------------------------------------------------------------------------------------    @Nullable	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));		}    	// 通过反射执行真实的处理器方法,获取处理器方法执行后的返回值,此处就是调用Controller中的方法		return doInvoke(args);	}-----------------------------------------------------------------------------------------    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);            // 解析通过providedArgs提供的预留参数,当providedArgs中有与当前遍历的参数类型匹配的参数值时,直接使用该值作为最终调用的参数值,在处理器方法调用时,providedArgs为空,但在异常解析方法与@InitBinder方法调用时,有额外提供的参数			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;	}

if (!this.resolvers.supportsParameter(parameter))

@Overridepublic boolean supportsParameter(MethodParameter parameter) {   	// 返回的参数解析器不为空,则视为支持	return getArgumentResolver(parameter) != null;}   @Nullableprivate HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {   	// 优先从缓存中获取	HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);	// 如果缓存为空   	if (result == null) {           // 执行遍历判断逻辑,遍历内部的全部参数解析器		for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {               //执行参数解析器的判断逻辑,判断当前遍历中参数解析器是否支持当前参数			if (resolver.supportsParameter(parameter)) {                   // 如果支持,则指定result为当前参数解析器,并添加到缓存				result = resolver;				this.argumentResolverCache.put(parameter, result);				break;			}		}	}   	// 返回支持该参数的参数解析器	return result;}

args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {		// 执行获取参数解析器逻辑,直接从缓存中获取		HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);    	// 一般不会等于空		if (resolver == null) {			throw new IllegalArgumentException("Unsupported parameter type [" +					parameter.getParameterType().getName() + "]. supportsParameter should be called first.");		}    	// 执行这个参数解析器的解析参数逻辑		return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);	}

this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

@Override	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {		// 选择返回值处理器列表中支持当前返回值的处理器		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);		// 如果为空,则表示无法处理返回值,抛出异常        if (handler == null) {			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());		}        // 调用选择的返回值处理器的处理返回值方法,对返回值及返回值相关的MV容器及Web请求进行处理,返回值处理器的返回逻辑不返回任何结果,处理后的结果都是通过MV传递		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);	}-----------------------------------------------------------------------------------------@Nullable	private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {    	// 判断返回值是否是异步类型,但此处判断逻辑默认都是false,因为所有的异步结构都是作为同步结果进行处理的,在同步结果的处理器中做溢写异步操作实现异步结果的处理		boolean isAsyncValue = isAsyncReturnValue(value, returnType);    	// 遍历当前组合组件封装的全部返回值处理器		for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {            // 如果是异步结果,且当前处理器不是异步返回值处理器,则直接跳过			if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {				continue;			}            // 判断当前遍历中返回值处理器是否支持该返回值类型,如果支持则直接返回,一个结果只能有一个返回值处理器			if (handler.supportsReturnType(returnType)) {				return handler;			}		}		return null;	}
6、getModelAndView(mavContainer, modelFactory, webRequest);
@Nullable	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {		// 通过model工厂更新model中的值		modelFactory.updateModel(webRequest, mavContainer);        // 如果是已经处理过的请求,则返回的MV为空,后续不再执行处理		if (mavContainer.isRequestHandled()) {			return null;		}        // 获取MV容器中的ModelMap,包含了所有的Model属性		ModelMap model = mavContainer.getModel();        // 创建新的MV对象		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());        //如果容器中的视图不是视图名引用		if (!mavContainer.isViewReference()) {            // 直接设置返回ModelAndView中的视图			mav.setView((View) mavContainer.getView());		}        // 如果模型属性是RediretAttributes类型,说明是通过RedirectAttributes类型引入的参数添加的模型属性值,即重定向属性		if (model instanceof RedirectAttributes) {            // 获取重定向模型属性中需要留给重定向后请求使用的闪存属性			Map flashAttributes = ((RedirectAttributes) model).getFlashAttributes();            // 通过传入的请求封装获取原始的请求			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);            // 如果请求不为空			if (request != null) {                // 把重定向的删除属性添加到当前请求的输出FlashMap中				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);			}		}		return mav;	}