SpringMVC DispatcherServlet源码(3) 请求分发流程

29 篇文章 0 订阅
6 篇文章 0 订阅

本文介绍DispatcherServlet的请求转发流程,包括:

  1. 从HandlerMapping集查找可以处理该请求的执行器链
  2. 从HandlerAdapter集查找支持当前请求的Adapter
  3. 执行拦截器preHandle方法
  4. 处理请求接收ModelAndView返回值
  5. 执行拦截器postHandle方法
  6. 处理接口返回值
  7. 执行拦截器afterCompletion方法

doService方法

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

	// Keep a snapshot of the request attributes in case of an include,
	// to be able to restore the original attributes after the include.
    // 当前请求发生转发即forward操作,需要保存请求的当前状态,通常不需要
	Map<String, Object> attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(request)) {
		attributesSnapshot = new HashMap<>();
		Enumeration<?> attrNames = request.getAttributeNames();
		while (attrNames.hasMoreElements()) {
			String attrName = (String) attrNames.nextElement();
			if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
				attributesSnapshot.put(attrName, request.getAttribute(attrName));
			}
		}
	}

	// Make framework objects available to handlers and view objects.
    // 设置一些Attribute,比如ApplicationContext,可以在Controller里面使用request.getAttribute出来使用
	request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
	request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
	request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
	request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

	if (this.flashMapManager != null) {
		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		if (inputFlashMap != null) {
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
	}

	try {
        // 分发请求
		doDispatch(request, response);
	} finally {
		if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Restore the original attribute snapshot, in case of an include.
			if (attributesSnapshot != null) {
				restoreAttributesAfterInclude(request, attributesSnapshot);
			}
		}
	}
}

doDispatch方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	boolean multipartRequestParsed = false;

	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

	try {
		ModelAndView mv = null;
		Exception dispatchException = null;

		try {
            // 封装Multipart请求
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

            // 1. 从HandlerMapping集查找可以处理该请求的执行器链
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null) {
                // 404
				noHandlerFound(processedRequest, response);
				return;
			}

            // 2. 从HandlerAdapter集查找支持当前请求的Adapter
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}

            // 3. 执行拦截器preHandle方法
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

            // 4. 处理请求接收ModelAndView返回值
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}

			applyDefaultViewName(processedRequest, mv);

            // 5. 执行拦截器postHandle方法
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		} catch (Exception ex) {
			dispatchException = ex;
		} catch (Throwable err) {
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
        // 6. 处理接口返回值
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	} catch (Exception ex) {
        // 7. 执行拦截器afterCompletion方法
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	} catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new NestedServletException("Handler processing failed", err));
	} finally {
		if (asyncManager.isConcurrentHandlingStarted()) {
			// Instead of postHandle and afterCompletion
			if (mappedHandler != null) {
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			}
		} else {
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}
}

流程:

  1. 从HandlerMapping集查找可以处理该请求的执行器链
  2. 从HandlerAdapter集查找支持当前请求的Adapter
  3. 执行拦截器preHandle方法
  4. 处理请求接收ModelAndView返回值
  5. 执行拦截器postHandle方法
  6. 处理接口返回值
    1. 如果有异常,则处理异常
    2. 渲染ModelAndView
    3. 执行拦截器afterCompletion方法
  7. 出现异常时,执行拦截器afterCompletion方法

流程分析

查找执行器链

入口

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
	}
	return null;
}

前文介绍,handlerMappings封装着所有的HandlerMapping:

在这里插入图片描述

其中RequestMappingHandlerMapping封装着所有的Controller接口处理方法映射,《扫描Controller创建HandlerMapping流程》已做过分析,此处介绍一下他的getHandler方法实现。

其余的几个HandlerMapping实现类后续会有专门章节介绍。

RequestMappingHandlerMapping的getHandler方法

方法实现在AbstractHandlerMapping类,使用了模板方法模式:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 模板方法,实现代码在AbstractHandlerMethodMapping类
    // 本文分析场景下返回的是HandlerMethod对象
	Object handler = getHandlerInternal(request);
	if (handler == null) {
		handler = getDefaultHandler();
	}
	if (handler == null) {
		return null;
	}
	// Bean name or resolved handler?
	if (handler instanceof String) {
		String handlerName = (String) handler;
		handler = obtainApplicationContext().getBean(handlerName);
	}

    // 封装执行器
	HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

	// 略

	return executionChain;
}

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    // 解析请求uri
	String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
	request.setAttribute(LOOKUP_PATH, lookupPath);
	this.mappingRegistry.acquireReadLock();
	try {
        // 从mappingRegistry查找HandlerMethod
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        // 这个步骤使用xxController组件名到spring容器查找对应的Controller组件Bean
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	} finally {
		this.mappingRegistry.releaseReadLock();
	}
}

查找HandlerMethod

protected HandlerMethod lookupHandlerMethod(
    	String lookupPath, HttpServletRequest request) throws Exception {

	List<Match> matches = new ArrayList<>();
    // 1. 查找直接匹配的、不含有path参数、不含有请求参数的RequestMappingInfo映射集
	List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
	if (directPathMatches != null) {
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
        // 2. 从所有RequestMappingInfo映射集查找
		addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
	}

    // 3. 如果查找到了两个或以上的RequestMappingInfo映射,需要比对一下
    // 如果上一步查找出了多个Match,则需要选择一个最优Match
    // 代码实现就是对Match集进行排序,内部会将两个RequestMappingInfo与当前请求匹配,匹配度较高者排在前面
	if (!matches.isEmpty()) {
		Match bestMatch = matches.get(0);
		if (matches.size() > 1) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			matches.sort(comparator);
			bestMatch = matches.get(0);
			if (CorsUtils.isPreFlightRequest(request)) {
				return PREFLIGHT_AMBIGUOUS_MATCH;
			}
			Match secondBestMatch = matches.get(1);
			if (comparator.compare(bestMatch, secondBestMatch) == 0) {
				Method m1 = bestMatch.handlerMethod.getMethod();
				Method m2 = secondBestMatch.handlerMethod.getMethod();
				String uri = request.getRequestURI();
				throw new IllegalStateException(
						"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
			}
		}
		request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
		handleMatch(bestMatch.mapping, lookupPath, request);
		return bestMatch.handlerMethod;
	} else {
		return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
	}
}

查找HandlerMethod - 匹配RequestMappingInfo映射

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
    // 这里的T是RequestMappingInfo
    // 遍历RequestMappingInfo集
	for (T mapping : mappings) {
        // 与当前请求匹配
		T match = getMatchingMapping(mapping, request);
		if (match != null) {
            // 使用RequestMappingInfo、HandlerMethod封装Match对象
			matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
		}
	}
}

// RequestMappingInfoHandlerMapping.getMatchingMapping方法
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
    // 把当前请求与RequestMappingInfo的一系列Condition匹配
	return info.getMatchingCondition(request);
}

看一下info.getMatchingCondition方法:

public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
    // 匹配请求Method
    // methodsCondition封装着该RequestMappingInfo支持的Method集
    // 返回null表示不支持当前请求
	RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
	if (methods == null) {
		return null;
	}
    // 匹配RequestMapping注解的params值
	ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
	if (params == null) {
		return null;
	}
    // 匹配RequestMapping注解的headers值
	HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
	if (headers == null) {
		return null;
	}
    // 匹配Content-Type
	ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
	if (consumes == null) {
		return null;
	}
    // 匹配Accept
	ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
	if (produces == null) {
		return null;
	}
    // 匹配path
    // 内部封装着RequestMapping注解的path值
    // 使用AntPathMatcher去尝试匹配请求与path配置
	PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
	if (patterns == null) {
		return null;
	}
    // 匹配自定义Condition
	RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
	if (custom == null) {
		return null;
	}

    // 匹配成功时返回
	return new RequestMappingInfo(this.name, patterns,
			methods, params, headers, consumes, produces, custom.getCondition());
}

查找支持的Adapter

入口

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

getHandlerAdapter方法:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	if (this.handlerAdapters != null) {
		for (HandlerAdapter adapter : this.handlerAdapters) {
			if (adapter.supports(handler)) {
				return adapter;
			}
		}
	}
	throw new ServletException("No adapter for handler");
}

前文介绍,handlerAdapters封装着所有的HandlerAdapter:

在这里插入图片描述

其中RequestMappingHandlerAdapter用于处理被@RequestMapping标注的HandlerMethod,《扫描Controller创建HandlerMapping流程》已做过分析,此处介绍一下他的supports方法实现。

其余的几个HandlerAdapter实现类后续会有专门章节介绍。

RequestMappingHandlerAdapter的supports方法

public final boolean supports(Object handler) {
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

执行拦截器preHandle方法

// 执行拦截器preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
	return;
}

HandlerExecutionChain.applyPreHandle方法:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HandlerInterceptor[] interceptors = getInterceptors();
	if (!ObjectUtils.isEmpty(interceptors)) {
		for (int i = 0; i < interceptors.length; i++) {
			HandlerInterceptor interceptor = interceptors[i];
			if (!interceptor.preHandle(request, response, this.handler)) {
				triggerAfterCompletion(request, response, null);
				return false;
			}
			this.interceptorIndex = i;
		}
	}
	return true;
}

调用执行器处理请求

入口

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

上文已经介绍,此处ha是RequestMappingHandlerAdapter类型对象。

handle方法:

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
	return handleInternal(request, response, (HandlerMethod) handler);
}

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

	ModelAndView mav;
	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...
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}

	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		} else {
			prepareResponse(response);
		}
	}

	return mav;
}

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

        // model and view相关配置
		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();
			invocableMethod = invocableMethod.wrapConcurrentResult(result);
		}

        // 调用处理器handle
		invocableMethod.invokeAndHandle(webRequest, mavContainer);

		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}

        // 封装ModelAndView
		return getModelAndView(mavContainer, modelFactory, webRequest);
	} finally {
		webRequest.requestCompleted();
	}
}

ServletInvocableHandlerMethod.invokeAndHandle

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);
	try {
        // 处理接口返回值
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	} catch (Exception ex) {
		throw ex;
	}
}

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {
	// 解析参数
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    // 调用目标方法
	return doInvoke(args);
}

protected Object[] getMethodArgumentValues(NativeWebRequest request, 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); // null
		if (args[i] != null) {
			continue;
		}
        // 解析参数
		try {
			args[i] = this.resolvers
                .resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		} catch (Exception ex) {
			throw ex;
		}
	}
	return args;
}

解析参数

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

resolvers是HandlerMethodArgumentResolverComposite对象,里面封装着系统配置的所有的参数解析器:

在这里插入图片描述

resolveArgument方法内部首先查找能够处理当前参数的解析器,之后调用解析器resolveArgument方法解析参数,以RequestResponseBodyMethodProcessor实现类为例:

  • Resolves method arguments annotated with @RequestBody and handles return values from methods annotated with @ResponseBody by reading and writing to the body of the request or response with an HttpMessageConverter.
  • An @RequestBody method argument is also validated if it is annotated with @javax.validation.Valid. In case of validation failure, MethodArgumentNotValidException is raised and results in an HTTP 400 response status code if DefaultHandlerExceptionResolver is configured.

supportsParameter方法:

public boolean supportsParameter(MethodParameter parameter) {
	return parameter.hasParameterAnnotation(RequestBody.class);
}

resolveArgument方法:

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

	parameter = parameter.nestedIfOptional();
    // 使用MessageConverter读取
    // 从当前封装的MessageConverter集查找支持当前参数的Converter对象,使用canRead方法判断
    // 使用Converter对象read方法解析参数
	Object arg = readWithMessageConverters(
        webRequest, parameter, parameter.getNestedGenericParameterType());
	String name = Conventions.getVariableNameForParameter(parameter);

    // 参数验证,这里不展开分析了
	if (binderFactory != null) {
		WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
		if (arg != null) {
			validateIfApplicable(binder, parameter);
			if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
				throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
			}
		}
		if (mavContainer != null) {
			mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
		}
	}

    // optional包装
	return adaptArgumentIfNecessary(arg, parameter);
}

解析参数 - MessageConverter

MessageConverter接口:

public interface HttpMessageConverter<T> {

	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

	List<MediaType> getSupportedMediaTypes();

	T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException;

	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException;
}

上文使用的RequestResponseBodyMethodProcessor封装了系统支持的MessageConverter集:

在这里插入图片描述

其中MappingJackson2HttpMessageConverter使用Jackson ObjectMapper读写json请求和响应:

  • By default, this converter supports application/json and application/*+json with UTF-8 character set. This can be overridden by setting the supportedMediaTypes property.
  • The default constructor uses the default configuration provided by Jackson2ObjectMapperBuilder.
  • Compatible with Jackson 2.9 and higher, as of Spring 5.0.

其余的MessageConverter实现后续会介绍。

调用目标方法

protected Object doInvoke(Object... args) throws Exception {
	ReflectionUtils.makeAccessible(getBridgedMethod());
	try {
        // 调用目标方法
        // If the bean method is a bridge method,
        // this method returns the bridged (user-defined) method.
        // Otherwise it returns the same method as getMethod().
		return getBridgedMethod().invoke(getBean(), args);
	} catch (IllegalArgumentException ex) {
		assertTargetBean(getBridgedMethod(), getBean(), args);
		String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
		throw new IllegalStateException(formatInvokeError(text, args), ex);
	} catch (InvocationTargetException ex) {
		// Unwrap for HandlerExceptionResolvers ...
		Throwable targetException = ex.getTargetException();
		if (targetException instanceof RuntimeException) {
			throw (RuntimeException) targetException;
		} else if (targetException instanceof Error) {
			throw (Error) targetException;
		} else if (targetException instanceof Exception) {
			throw (Exception) targetException;
		} else {
			throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
		}
	}
}

处理接口返回值

// 处理接口返回值
this.returnValueHandlers.handleReturnValue(
		returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

returnValueHandlers是HandlerMethodReturnValueHandlerComposite对象,里面封装着系统配置的所有的返回值解析器:

在这里插入图片描述

handleReturnValue方法内部首先查找能够匹配当前返回值的处理器,之后调用处理器handleReturnValue方法处理参数,以RequestResponseBodyMethodProcessor实现类为例,这个类既实现了HandlerMethodArgumentResolver,也实现了HandlerMethodReturnValueHandler,所以他既能解析被@RequestBody标注的参数,也能处理被@ResponseBody标注的返回值。

supportsReturnType方法:

public boolean supportsReturnType(MethodParameter returnType) {
	return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
			returnType.hasMethodAnnotation(ResponseBody.class));
}

handleReturnValue方法:

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

	mavContainer.setRequestHandled(true);

	ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
	ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

	// Try even with null return value. ResponseBodyAdvice could get involved.
    // 使用MessageConverter进行序列化之类的操作然后写出到数据流
    // 从当前封装的MessageConverter集查找支持当前返回值的Converter对象,使用canWrite方法判断
    // 使用Converter对象write方法序列化、写输出流
	writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

封装ModelAndView

在目标方法处理完毕,就要封装ModelAndView并返回,在RequestMappingHandlerAdapter的invokeHandlerMethod方法中:

return getModelAndView(mavContainer, modelFactory, webRequest);

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

这里再介绍一下ModelAndViewMethodReturnValueHandler处理器,他用来处理ModelAndView类型返回值。

handleReturnValue方法:

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

	if (returnValue == null) {
		mavContainer.setRequestHandled(true);
		return;
	}

	ModelAndView mav = (ModelAndView) returnValue;
	if (mav.isReference()) {
		String viewName = mav.getViewName();
		mavContainer.setViewName(viewName);
		if (viewName != null && isRedirectViewName(viewName)) {
			mavContainer.setRedirectModelScenario(true);
		}
	} else {
		View view = mav.getView();
		mavContainer.setView(view);
		if (view instanceof SmartView && ((SmartView) view).isRedirectView()) {
			mavContainer.setRedirectModelScenario(true);
		}
	}
	mavContainer.setStatus(mav.getStatus());
	mavContainer.addAllAttributes(mav.getModel());
}

执行拦截器postHandle方法

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)
		throws Exception {

	HandlerInterceptor[] interceptors = getInterceptors();
	if (!ObjectUtils.isEmpty(interceptors)) {
		for (int i = interceptors.length - 1; i >= 0; i--) {
			HandlerInterceptor interceptor = interceptors[i];
			interceptor.postHandle(request, response, this.handler, mv);
		}
	}
}

处理ModelAndView返回值

// 处理接口返回值
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

processDispatchResult方法:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
		@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
		@Nullable Exception exception) throws Exception {

	boolean errorView = false;

	if (exception != null) {
		if (exception instanceof ModelAndViewDefiningException) {
			mv = ((ModelAndViewDefiningException) exception).getModelAndView();
		} else {
            // 处理异常
			Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
			mv = processHandlerException(request, response, handler, exception);
			errorView = (mv != null);
		}
	}

	// 使用ModelAndView渲染页面
	if (mv != null && !mv.wasCleared()) {
		render(mv, request, response);
		if (errorView) {
			WebUtils.clearErrorRequestAttributes(request);
		}
	} else {
		
	}

	if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
		// Concurrent handling started during a forward
		return;
	}

    // 执行拦截器afterCompletion方法
	if (mappedHandler != null) {
		// Exception (if any) is already handled..
		mappedHandler.triggerAfterCompletion(request, response, null);
	}
}

处理异常

如果有异常,则处理异常。

processHandlerException方法:

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
		@Nullable Object handler, Exception ex) throws Exception {

	// Success and error responses may use different content types
	request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);

	// Check registered HandlerExceptionResolvers...
	ModelAndView exMv = null;
    // 使用HandlerExceptionResolver集处理异常
	if (this.handlerExceptionResolvers != null) {
		for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
			exMv = resolver.resolveException(request, response, handler, ex);
			if (exMv != null) {
				break;
			}
		}
	}
    // ModelAndView处理
	if (exMv != null) {
		if (exMv.isEmpty()) {
			request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
			return null;
		}
		// We might still need view name translation for a plain error model...
		if (!exMv.hasView()) {
			String defaultViewName = getDefaultViewName(request);
			if (defaultViewName != null) {
				exMv.setViewName(defaultViewName);
			}
		}
		WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
		return exMv;
	}

	throw ex;
}

HandlerExceptionResolver集:

在这里插入图片描述

  • DefaultErrorAttributes - Spring Boot提供,暂不分析
  • HandlerExceptionResolverComposite - Spring MVC的异常处理器,他是在WebMvcConfigurationSupport中注入到Spring容器的,会扫描被@ControllerAdvice标注的Bean,封装ControllerAdviceBean和ExceptionHandlerMethodResolver

ExceptionHandlerExceptionResolver类封装着Controller的异常处理通知集:

  • exceptionHandlerCache - 保存Controller类里面被@ExceptionHandler注解标注的异常处理方法
  • exceptionHandlerAdviceCache - 保存被@ControllerAdvice标注的异常处理方法

在此处,会遍历HandlerExceptionResolver集,调用resolveException方法处理异常,我们重点看一下ExceptionHandlerExceptionResolver的实现方式:

  • 从当前Controller类中查找能够处理该异常的ExceptionHandler方法,如果找到,就使用他来处理
  • 如果上一步没找到,则在ControllerAdvice异常处理方法中查找,如果找到,就使用他来处理
  • 如果上一步没找到,会返回null,之后会进入下一轮迭代,尝试使用ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver处理

渲染ModelAndView

protected void render(
    ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {

	// Determine locale for request and apply it to the response.
	Locale locale =
			(this.localeResolver != null ?
             this.localeResolver.resolveLocale(request) : request.getLocale());
	response.setLocale(locale);

	View view;
	String viewName = mv.getViewName();
	if (viewName != null) {
		// We need to resolve the view name.
        // 使用视图解析器查找视图
		view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
		if (view == null) {
			throw new ServletException("Could not resolve view");
		}
	} else {
		// No need to lookup: the ModelAndView object contains the actual View object.
		view = mv.getView();
		if (view == null) {
			throw new ServletException("xxx");
		}
	}

	try {
		if (mv.getStatus() != null) {
			response.setStatus(mv.getStatus().value());
		}
        // 渲染视图
		view.render(mv.getModelInternal(), request, response);
	} catch (Exception ex) {
		throw ex;
	}
}

执行拦截器afterCompletion方法

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
		throws Exception {

	HandlerInterceptor[] interceptors = getInterceptors();
	if (!ObjectUtils.isEmpty(interceptors)) {
		for (int i = this.interceptorIndex; i >= 0; i--) {
			HandlerInterceptor interceptor = interceptors[i];
			try {
				interceptor.afterCompletion(request, response, this.handler, ex);
			} catch (Throwable ex2) {
				logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
			}
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值