SpringMVC4.x源码分析(四):一个request请求的完整流程和各组件介绍

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

本节主要目标是探查一个request请求的完整流程,以及流程中各种web组件的简单介绍,组件的细节,将在后续组件专题文章中详细介绍。

DispatcherServlet初始化完毕后,我们发现它注册2个HandlerMapping,3个HandlerAdapter,主要是为了兼容旧的过时的Controllor编写模式,在本例中,实际生效的是RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

caa10a96e26fff5491deb535cde0c6dfdd3.jpg

aa1724b7c979ea63077956226f7ebb6f439.jpg

我们来看看这几个对象是什么时候注册进去的。

AnnotationDrivenBeanDefinitionParser#parse()方法中,有一段:

// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
	registerBeanNameUrlHandlerMapping(parserContext, source);
	registerHttpRequestHandlerAdapter(parserContext, source);
	registerSimpleControllerHandlerAdapter(parserContext, source);
	registerHandlerMappingIntrospector(parserContext, source);
}

BeanNameUrlHandlerMapping用于处理如下形式的Controllor(已过时):

public class SomeControllor implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}

RequestMappingHandlerMapping是本例真正使用的处理@RequestMapping形式的Controllor。同理,本例使用RequestMappingHandlerAdapter,其余读者可自行查看。

RequestMappingHandlerAdapter的初始化:

RequestMappingHandlerAdapter同样实现了InitializingBean接口,实例化对象时,会调用afterPropertiesSet()方法。

@Override
public void afterPropertiesSet() {
	// 初始化@ControllerAdvice标注的类
	initControllerAdviceCache();
    // 参数解析器
	if (this.argumentResolvers == null) {
		List resolvers = getDefaultArgumentResolvers();
		this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
	}
    // @InitBinder标注的方法参数处理器
	if (this.initBinderArgumentResolvers == null) {
		List resolvers = getDefaultInitBinderArgumentResolvers();
		this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
	}
    // 返回值处理器
	if (this.returnValueHandlers == null) {
		List handlers = getDefaultReturnValueHandlers();
		this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
	}
}

从源码中我们看到了四个重要信息:@ControllerAdvice、@InitBinder、argumentResolvers、returnValueHandlers。

其中argumentResolvers和returnValueHandlers会用到HttpMessageConverter消息转换器,用以处理@ResponseBody和@RequestBody所标注的方法或参数。

private List getDefaultArgumentResolvers() {
	List resolvers = new ArrayList();

	// Annotation-based argument resolution
	resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
	resolvers.add(new RequestParamMapMethodArgumentResolver());
	resolvers.add(new PathVariableMethodArgumentResolver());
	resolvers.add(new PathVariableMapMethodArgumentResolver());
	resolvers.add(new MatrixVariableMethodArgumentResolver());
	resolvers.add(new MatrixVariableMapMethodArgumentResolver());
	resolvers.add(new ServletModelAttributeMethodProcessor(false));
    // 使用消息转换器
	resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    // 使用消息转换器
	resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
	resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
	resolvers.add(new RequestHeaderMapMethodArgumentResolver());
	resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
	resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
	resolvers.add(new SessionAttributeMethodArgumentResolver());
	resolvers.add(new RequestAttributeMethodArgumentResolver());

	// Type-based argument resolution
	resolvers.add(new ServletRequestMethodArgumentResolver());
	resolvers.add(new ServletResponseMethodArgumentResolver());
    // 使用消息转换器
	resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
	resolvers.add(new RedirectAttributesMethodArgumentResolver());
	resolvers.add(new ModelMethodProcessor());
	resolvers.add(new MapMethodProcessor());
	resolvers.add(new ErrorsMethodArgumentResolver());
	resolvers.add(new SessionStatusMethodArgumentResolver());
	resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

	// Custom arguments
	if (getCustomArgumentResolvers() != null) {
		resolvers.addAll(getCustomArgumentResolvers());
	}

	// Catch-all
	resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
	resolvers.add(new ServletModelAttributeMethodProcessor(true));

	return resolvers;
}

方法getMessageConverters()获取的,就是默认的HttpMessageConverter消息转换器。

RequestMappingHandlerAdapter的构造函数,会默认加入4个消息转换器,但是,遗憾的是,它会被Spring自动注入的消息转换器给覆盖掉。

public RequestMappingHandlerAdapter() {
	StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
	stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316

	this.messageConverters = new ArrayList>(4);
	this.messageConverters.add(new ByteArrayHttpMessageConverter());
	this.messageConverters.add(stringHttpMessageConverter);
	this.messageConverters.add(new SourceHttpMessageConverter());
	this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}

覆盖逻辑:AnnotationDrivenBeanDefinitionParser#getMessageConverters()方法返回的消息转换器,会覆盖构造函数加入的默认转换器:

private ManagedList getMessageConverters(Element element, Object source, ParserContext parserContext) {
	Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
	ManagedList messageConverters = new ManagedList();
	if (convertersElement != null) {
		messageConverters.setSource(source);
		for (Element beanElement : DomUtils.getChildElementsByTagName(convertersElement, "bean", "ref")) {
			Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
			messageConverters.add(object);
		}
	}

	if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
		messageConverters.setSource(source);
		messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));

		RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
		stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
		messageConverters.add(stringConverterDef);

		messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
		messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
		messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));

		if (romePresent) {
			messageConverters.add(createConverterDefinition(AtomFeedHttpMessageConverter.class, source));
			messageConverters.add(createConverterDefinition(RssChannelHttpMessageConverter.class, source));
		}

		if (jackson2XmlPresent) {
			Class type = MappingJackson2XmlHttpMessageConverter.class;
			RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
			GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
			jacksonFactoryDef.getPropertyValues().add("createXmlMapper", true);
			jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
			messageConverters.add(jacksonConverterDef);
		}
		else if (jaxb2Present) {
			messageConverters.add(createConverterDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
		}

		if (jackson2Present) {
			Class type = MappingJackson2HttpMessageConverter.class;
			RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
			GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
			jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
			messageConverters.add(jacksonConverterDef);
		}
		else if (gsonPresent) {
			messageConverters.add(createConverterDefinition(GsonHttpMessageConverter.class, source));
		}
	}
	return messageConverters;
} 
   

核心分发器DispatcherServlet的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 {
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

			// 返回RequestMappingHandlerMapping生成的chain对象.
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// 返回RequestMappingHandlerAdapter对象.
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (logger.isDebugEnabled()) {
					logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
				}
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}
              // 调用拦截器的preHandle()方法
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// 处理请求,返回ModelAndView对象.
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

			applyDefaultViewName(processedRequest, mv);
            // 调用拦截器的postHandle()方法
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		catch (Throwable err) {
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
        // ViewResolver处理结果视图
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
        // 调用拦截器的afterCompletion()方法
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new NestedServletException("Handler processing failed", err));
	}
	finally {
        //...
	}
}

InvocableHandlerMethod#invokeForRequest()方法中,使用argumentResolvers处理入参:

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {
    // 使用argumentResolvers处理入参
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    // 调用Controllor的目标方法
	Object returnValue = doInvoke(args);
	
	return returnValue;
}

ServletInvocableHandlerMethod#invokeAndHandle()方法中,使用returnValueHandlers处理方法返回值:

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

	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	//...
	try {
		this.returnValueHandlers.handleReturnValue(
				returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		//...
		}
		throw ex;
	}
}

DispatcherServlet#render()方法中,使用viewResolvers解析View,并使用View渲染视图:

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	Locale locale = this.localeResolver.resolveLocale(request);
	response.setLocale(locale);

	View view;
	if (mv.isReference()) {
		// 使用viewResolvers解析出View
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		//...
	}
	else {
		//...
	}
	try {
		if (mv.getStatus() != null) {
			response.setStatus(mv.getStatus().value());
		}
        // view渲染视图
		view.render(mv.getModelInternal(), request, response);
	}
	catch (Exception ex) {
		//...
	}
}

至此,一个reqeust请求的完整流程,就结束了,流程中,我们看到了一些非常重要的注解和组件。

注解:@ControllerAdvice、@InitBinder、@ResponseBody和@RequestBody

组件:HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler、HandlerInterceptor、HttpMessageConverter、ViewResolver

后续我们会对这些注解和组件,进行详细的分析。

补充:

本例我们并没有注册任何自定义的拦截器,但是,我们发现依然有一个ConversionServiceExposingInterceptor拦截器。

f3dd2b912edc595e683ad10e538b316e6b9.jpg

public class ConversionServiceExposingInterceptor extends HandlerInterceptorAdapter {

	private final ConversionService conversionService;

	public ConversionServiceExposingInterceptor(ConversionService conversionService) {
		Assert.notNull(conversionService, "The ConversionService may not be null");
		this.conversionService = conversionService;
	}


	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws ServletException, IOException {

		request.setAttribute(ConversionService.class.getName(), this.conversionService);
		return true;
	}

}

该拦截器给每一个reqeust请求放入一个ConversionService,那该拦截器是什么时候注册和创建的呢?

RequestMappingHandlerMapping实现了ApplicationContextAware接口,其父类会调用AbstractHandlerMapping#initApplicationContext()方法,该方法会自动加入ConversionServiceExposingInterceptor拦截器:

protected void initApplicationContext() throws BeansException {
	//...
	detectMappedInterceptors(this.adaptedInterceptors);
	//...
}

protected void detectMappedInterceptors(List mappedInterceptors) {
	mappedInterceptors.addAll(
			BeanFactoryUtils.beansOfTypeIncludingAncestors(
					getApplicationContext(), MappedInterceptor.class, true, false).values());
}

这其中,MappedInterceptor类里,持有了ConversionServiceExposingInterceptor拦截器,是默认加入的。

原文出处:http://my.oschina.net/zudajun

转载于:https://my.oschina.net/zudajun/blog/1828434

你可能感兴趣的:(SpringMVC4.x源码分析(四):一个request请求的完整流程和各组件介绍)