Springmvc 工作机制源码分析

Springmvc整体工作流程

        DispatcherServlet本质是HttpServlet,是Springmvc的http请求分发控制器,是Springmvc整体工作流程的核心。

DispatcherServlet类结构继承图


在../WEB-INF/web.xml中配置如下:

<servlet>
	<servlet-name>springmvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		  <param-name>contextConfigLocation</param-name>
		  <param-value>/WEB-INF/classes/META-INF/spring/springmvc-servlet.xml</param-value>
	  </init-param>
	  <!-- <load-on-startup>1</load-on-startup> -->
</servlet>
 
<servlet-mapping>
	<servlet-name>springmvc</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

         通过在web.xml中配置contextConfigLocation,指定了Springmvc的核心配置文件。

Springmvc整体工作流程示意图


Springmvc整体工作流程实现简图


初始化

           Springmvc的初始化体现为DispatcherServlet的初始化:1)完成Springmvc容器XmlWebApplicationContext的创建、配置及refresh;2)完成其组件的初始化。

Springmvc核心配置文件springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        					http://www.springframework.org/schema/context 
        					http://www.springframework.org/schema/context/spring-context-3.0.xsd
        					http://www.springframework.org/schema/mvc 
        					http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">                    
 
    <!-- scan the package and the sub package -->
    <context:component-scan base-package="com.bitvalue"/>
 
    <!-- don't handle the static resource -->
    <mvc:default-servlet-handler />
 
    <!-- if you use annotation you must configure following setting -->
    <mvc:annotation-driven />
     
    <!-- configure the InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/pages/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> 
    </bean>
    
    <!-- 支持上传文件 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

	<!-- 拦截器 -->
    <mvc:interceptors>
    	<mvc:interceptor>
    		<mvc:mapping path="/test/**" />
    		<bean class="org.test.interceptor.TestInterceptor"/> 
    	</mvc:interceptor>  
	</mvc:interceptors> 

</beans>

XmlWebApplicationContext容器的创建、配置及refresh


组件初始化


相关源码

         在“XmlWebApplicationContext容器的创建、配置及refresh”初始化阶段涉及Springmvc配置文件的解析及XmlWebApplicationContext容器中相关bean的实例化。

<mvc>标签元素解析

/** MvcNamespaceHandler.java */
public class MvcNamespaceHandler extends NamespaceHandlerSupport {

	// <mvc>相应标签元素解析
	public void init() {
		// 注册<mvc:annotation-driven />解析的BeanDefinitionParser
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		// 注册<mvc:default-servlet-handler />解析的BeanDefinitionParser
		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
		// 注册<mvc:interceptors />解析的BeanDefinitionParser
		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
		// 注册<mvc:resources />解析的BeanDefinitionParser
		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
		// 注册<mvc:view-controller />解析的BeanDefinitionParser
		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
	}

}

/** AnnotationDrivenBeanDefinitionParser.java */
public BeanDefinition parse(Element element, ParserContext parserContext) {
	Object source = parserContext.extractSource(element);

	CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
	parserContext.pushContainingComponent(compDefinition);

	RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);

	// RequestMappingHandlerMapping RootBeanDefinition
	RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
	handlerMappingDef.setSource(source);
	handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	handlerMappingDef.getPropertyValues().add("order", 0);
	handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
	String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
	if (element.hasAttribute("enableMatrixVariables")) {
		Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
		handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
	}

	RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
	RuntimeBeanReference validator = getValidator(element, source, parserContext);
	RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
	
	// ConfigurableWebBindingInitializer RootBeanDefinition
	RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
	bindingDef.setSource(source);
	bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	bindingDef.getPropertyValues().add("conversionService", conversionService);
	bindingDef.getPropertyValues().add("validator", validator);
	bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);

	ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
	ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);
	ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
	String asyncTimeout = getAsyncTimeout(element);
	RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
	ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, parserContext);
	ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, parserContext);

	// RequestMappingHandlerAdapter RootBeanDefinition
	RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
	handlerAdapterDef.setSource(source);
	handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
	handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
	handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
	if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
		Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));
		handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
	}
	if (argumentResolvers != null) {
		handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
	}
	if (returnValueHandlers != null) {
		handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
	}
	if (asyncTimeout != null) {
		handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
	}
	if (asyncExecutor != null) {
		handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
	}
	handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
	handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
	String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);

	// ConversionServiceExposingInterceptor RootBeanDefinition
	RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
	csInterceptorDef.setSource(source);
	csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
	// MappedInterceptor RootBeanDefinition
	RootBeanDefinition mappedCsInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
	mappedCsInterceptorDef.setSource(source);
	mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
	mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
	String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedCsInterceptorDef);

	// ExceptionHandlerExceptionResolver RootBeanDefinition
	RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
	exceptionHandlerExceptionResolver.setSource(source);
	exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
	exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
	exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
	String methodExceptionResolverName =
			parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);

	// ResponseStatusExceptionResolver RootBeanDefinition
	RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
	responseStatusExceptionResolver.setSource(source);
	responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	responseStatusExceptionResolver.getPropertyValues().add("order", 1);
	String responseStatusExceptionResolverName =
			parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);

	// DefaultHandlerExceptionResolver RootBeanDefinition
	RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
	defaultExceptionResolver.setSource(source);
	defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	defaultExceptionResolver.getPropertyValues().add("order", 2);
	String defaultExceptionResolverName =
			parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);

	parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
	parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
	parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
	parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
	parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
	parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));

	// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
	MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

	parserContext.popAndRegisterContainingComponent();

	return null;
}

/** DefaultServletHandlerBeanDefinitionParser.java */
public BeanDefinition parse(Element element, ParserContext parserContext) {
	Object source = parserContext.extractSource(element);

	String defaultServletName = element.getAttribute("default-servlet-name");
	// DefaultServletHttpRequestHandler RootBeanDefinition
	RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class);
	defaultServletHandlerDef.setSource(source);
	defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	if (StringUtils.hasText(defaultServletName)) {
		defaultServletHandlerDef.getPropertyValues().add("defaultServletName", defaultServletName);
	}
	String defaultServletHandlerName = parserContext.getReaderContext().generateBeanName(defaultServletHandlerDef);
	parserContext.getRegistry().registerBeanDefinition(defaultServletHandlerName, defaultServletHandlerDef);
	parserContext.registerComponent(new BeanComponentDefinition(defaultServletHandlerDef, defaultServletHandlerName));

	Map<String, String> urlMap = new ManagedMap<String, String>();
	urlMap.put("/**", defaultServletHandlerName);

	// SimpleUrlHandlerMapping RootBeanDefinition
	RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
	handlerMappingDef.setSource(source);
	handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	handlerMappingDef.getPropertyValues().add("urlMap", urlMap);

	String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);
	parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);
	parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));

	// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
	MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

	return null;
}

/** InterceptorsBeanDefinitionParser.java */
public BeanDefinition parse(Element element, ParserContext parserContext) {
	CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
	parserContext.pushContainingComponent(compDefinition);

	List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
	for (Element interceptor : interceptors) {
		// MappedInterceptor RootBeanDefinition
		RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
		mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
		mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

		ManagedList<String> includePatterns = null;
		ManagedList<String> excludePatterns = null;
		Object interceptorBean;
		if ("interceptor".equals(interceptor.getLocalName())) {
			includePatterns = getIncludePatterns(interceptor, "mapping");
			excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
			Element beanElem = DomUtils.getChildElementsByTagName(interceptor, "bean", "ref").get(0);
			interceptorBean = parserContext.getDelegate().parsePropertySubElement(beanElem, null);
		}
		else {
			interceptorBean = parserContext.getDelegate().parsePropertySubElement(interceptor, null);
		}
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);

		String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
		parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
	}

	parserContext.popAndRegisterContainingComponent();
	return null;
}

RequestMappingHandlerMapping bean初始化

        RequestMappingHandlerMapping的初始化主要工作为建立请求url与HandlerMethod的映射关系。

AbstractHandlerMapping类结构关系图:


时序图:


相关源码:

/** AbstractHandlerMethodMapping.java */
protected void detectHandlerMethods(final Object handler) {
	Class<?> handlerType =
			(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());

	// Avoid repeated calls to getMappingForMethod which would rebuild RequestMatchingInfo instances
	final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
	final Class<?> userType = ClassUtils.getUserClass(handlerType);

	// 查找userType中带@RequestMapping注解的method
	Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
		public boolean matches(Method method) {
			// 过滤带@RequestMapping注解的method,用@RequestMapping注解的属性值,new RequestMappingInfo
			T mapping = getMappingForMethod(method, userType);
			if (mapping != null) {
				mappings.put(method, mapping);
				return true;
			}
			else {
				return false;
			}
		}
	});

	for (Method method : methods) {
		//创建HandlerMethod且缓存其与url等的映射关系
		registerHandlerMethod(handler, method, mappings.get(method));
	}
}

/** RequestMappingHandlerMapping.java */
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
	RequestMappingInfo info = null;
	// method上的@RequestMapping注解对象
	RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
	if (methodAnnotation != null) {
		RequestCondition<?> methodCondition = getCustomMethodCondition(method);
		info = createRequestMappingInfo(methodAnnotation, methodCondition);
		// Class上的@RequestMapping注解对象
		RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
		if (typeAnnotation != null) {
			RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
			// 相关属性合并
			info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
		}
	}
	return info;
}

/** AbstractHandlerMethodMapping.java */
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
	//创建HandlerMethod
	HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
	HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping);
	if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {
		throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() +
				"' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" +
				oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");
	}

	//RequestMappingInfo到HandlerMethod映射
	this.handlerMethods.put(mapping, newHandlerMethod);
	if (logger.isInfoEnabled()) {
		logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
	}

	Set<String> patterns = getMappingPathPatterns(mapping);
	for (String pattern : patterns) {
		if (!getPathMatcher().isPattern(pattern)) {
			// url到RequestMappingInfo映射
			this.urlMap.add(pattern, mapping);
		}
	}
}

protected HandlerMethod createHandlerMethod(Object handler, Method method) {
	HandlerMethod handlerMethod;
	if (handler instanceof String) {
		String beanName = (String) handler;
		handlerMethod = new HandlerMethod(beanName, getApplicationContext(), method);
	}
	else {
		handlerMethod = new HandlerMethod(handler, method);
	}
	return handlerMethod;
}

/** RequestMappingInfoHandlerMapping.java */
protected Set<String> getMappingPathPatterns(RequestMappingInfo info) {
	return info.getPatternsCondition().getPatterns();
}

一次http请求处理流程

整体流程


getHandler流程

时序图:


相关源码:

/** AbstractHandlerMethodMapping.java */
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<Match>();
	// 根据url获取RequestMappingInfo
	List<T> directPathMatches = this.urlMap.get(lookupPath);
	if (directPathMatches != null) {
		// 匹配request的RequestMappingInfo
		addMatchingMappings(directPathMatches, matches, request);
	}
	if (matches.isEmpty()) {
		// No choice but to go through all mappings...
		addMatchingMappings(this.handlerMethods.keySet(), matches, request);
	}

	if (!matches.isEmpty()) {
		Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
		Collections.sort(matches, comparator);
		if (logger.isTraceEnabled()) {
			logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
		}
		// 最佳匹配request的Match
		Match bestMatch = matches.get(0);
		if (matches.size() > 1) {
			Match secondBestMatch = matches.get(1);
			if (comparator.compare(bestMatch, secondBestMatch) == 0) {
				Method m1 = bestMatch.handlerMethod.getMethod();
				Method m2 = secondBestMatch.handlerMethod.getMethod();
				throw new IllegalStateException(
						"Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" +
						m1 + ", " + m2 + "}");
			}
		}
		handleMatch(bestMatch.mapping, lookupPath, request);
		// 最佳匹配request的handlerMethod
		return bestMatch.handlerMethod;
	}
	else {
		return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
	}
}

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
	for (T mapping : mappings) {
		// 根据request,获取匹配的RequestMappingInfo
		T match = getMatchingMapping(mapping, request);
		if (match != null) {
			matches.add(new Match(match, this.handlerMethods.get(mapping)));
		}
	}
}

/** RequestMappingInfoHandlerMapping.java */
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
	return info.getMatchingCondition(request);
}

/** RequestMappingInfo.java */
// 根据request,获取匹配的RequestMappingInfo
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
	RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
	ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
	HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
	ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
	ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);

	if (methods == null || params == null || headers == null || consumes == null || produces == null) {
		return null;
	}

	PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
	if (patterns == null) {
		return null;
	}

	RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
	if (custom == null) {
		return null;
	}

	return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces, custom.getCondition());
}

/** RequestMappingInfoHandlerMapping.java */
protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {
	// request设置org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping属性
	super.handleMatch(info, lookupPath, request);

	String bestPattern;
	Map<String, String> uriVariables;
	Map<String, String> decodedUriVariables;

	Set<String> patterns = info.getPatternsCondition().getPatterns();
	if (patterns.isEmpty()) {
		bestPattern = lookupPath;
		uriVariables = Collections.emptyMap();
		decodedUriVariables = Collections.emptyMap();
	}
	else {
		bestPattern = patterns.iterator().next();
		uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
		decodedUriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables);
	}

	// request设置org.springframework.web.servlet.HandlerMapping.bestMatchingPattern属性
	request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
	// request设置org.springframework.web.servlet.HandlerMapping.uriTemplateVariables属性
	request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables);

	if (isMatrixVariableContentAvailable()) {
		Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(request, uriVariables);
		request.setAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
	}

	if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
		Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
		request.setAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes);
	}
}

/** AbstractHandlerMapping.java */
// 创建执行请求的处理链HandlerExecutionChain(拦截器+HandlerMethod)
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
	chain.addInterceptors(getAdaptedInterceptors());

	String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
	// 根据请求的lookupPath,获取匹配该url的拦截器
	for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
		if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
			chain.addInterceptor(mappedInterceptor.getInterceptor());
		}
	}

	return chain;
}

getHandlerAdapter流程

/** DispatcherServlet.java */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	for (HandlerAdapter ha : this.handlerAdapters) {
		if (logger.isTraceEnabled()) {
			logger.trace("Testing handler adapter [" + ha + "]");
		}
		if (ha.supports(handler)) {
			return ha;
		}
	}
	throw new ServletException("No adapter for handler [" + handler +
			"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

HandlerAdapter handle流程

HandlerAdapter类结构关系图:


时序图:


相关源码:

/** RequestMappingHandlerAdapter.java */
// 调用HandlerMethod返回结果ModelAndView
private ModelAndView invokeHandleMethod(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ServletWebRequest webRequest = new ServletWebRequest(request, response);

	//数据绑定Factory
	WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
	ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
	ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);

	//缓存调用结果Model、View
	ModelAndViewContainer mavContainer = new ModelAndViewContainer();
	mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
	modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
	mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

	AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
	asyncWebRequest.setTimeout(this.asyncRequestTimeout);

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

		if (logger.isDebugEnabled()) {
			logger.debug("Found concurrent result value [" + result + "]");
		}
		requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
	}

	// 调用HandlerMethod,且处理返回结果到mavContainer
	requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

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

	// 从mavContainer获取ModelAndView
	return getModelAndView(mavContainer, modelFactory, webRequest);
}

/** ServletInvocableHandlerMethod.java */
public final void invokeAndHandle(ServletWebRequest webRequest,
		ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {

	// 调用HandlerMethod
	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

	setResponseStatus(webRequest);

	if (returnValue == null) {
		if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	else if (StringUtils.hasText(this.responseReason)) {
		mavContainer.setRequestHandled(true);
		return;
	}

	mavContainer.setRequestHandled(false);

	try {
		// 处理returnValue,将结果ModelAndView中的ModelMap键值对合并到mavContainer
		this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
	catch (Exception ex) {
		if (logger.isTraceEnabled()) {
			logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
		}
		throw ex;
	}
}

/** InvocableHandlerMethod.java */
// 实际调用HandlerMethod
public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	// 获取HandlerMethod参数值
	Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
	if (logger.isTraceEnabled()) {
		StringBuilder sb = new StringBuilder("Invoking [");
		sb.append(getBeanType().getSimpleName()).append(".");
		sb.append(getMethod().getName()).append("] method with arguments ");
		sb.append(Arrays.asList(args));
		logger.trace(sb.toString());
	}
	// 利用反射实际调用HandlerMethod
	Object returnValue = invoke(args);
	if (logger.isTraceEnabled()) {
		logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
	}
	return returnValue;
}

private Object invoke(Object... args) throws Exception {
	ReflectionUtils.makeAccessible(getBridgedMethod());
	try {
		return getBridgedMethod().invoke(getBean(), args);
	}
	catch (IllegalArgumentException ex) {
		assertTargetBean(getBridgedMethod(), getBean(), args);
		throw new IllegalStateException(getInvocationErrorMessage(ex.getMessage(), 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 {
			String msg = getInvocationErrorMessage("Failed to invoke controller method", args);
			throw new IllegalStateException(msg, targetException);
		}
	}
}

/** HandlerMethodReturnValueHandlerComposite.java */
public void handleReturnValue(
		Object returnValue, MethodParameter returnType,
		ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
		throws Exception {

	// 获取ReturnValueHandler
	HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
	Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
	// 处理ReturnValue
	handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

/** ModelAndViewMethodReturnValueHandler.java */
public void handleReturnValue(
		Object returnValue, MethodParameter returnType,
		ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
		throws Exception {

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

	ModelAndView mav = (ModelAndView) returnValue;
	// viewName带"redirect:"则设置redirectModelScenario为true
	if (mav.isReference()) {
		String viewName = mav.getViewName();
		mavContainer.setViewName(viewName);
		if (viewName != null && viewName.startsWith("redirect:")) {
			mavContainer.setRedirectModelScenario(true);
		}
	}
	else {
		View view = mav.getView();
		mavContainer.setView(view);
		if (view instanceof SmartView) {
			if (((SmartView) view).isRedirectView()) {
				mavContainer.setRedirectModelScenario(true);
			}
		}
	}
	// mav中的ModelMap的属性键值对合并到mavContainer
	mavContainer.addAllAttributes(mav.getModel());
}

/** RequestMappingHandlerAdapter.java */
// 从mavContainer提取ModelAndView
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);
	if (!mavContainer.isViewReference()) {
		mav.setView((View) mavContainer.getView());
	}
	if (model instanceof RedirectAttributes) {
		Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
	}
	return mav;
}

processDispatchResult流程

/** DispatcherServlet.java */
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
		HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

	boolean errorView = false;

	if (exception != null) {
		if (exception instanceof ModelAndViewDefiningException) {
			logger.debug("ModelAndViewDefiningException encountered", exception);
			mv = ((ModelAndViewDefiningException) exception).getModelAndView();
		}
		else {
			Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
			mv = processHandlerException(request, response, handler, exception);
			errorView = (mv != null);
		}
	}

	// Did the handler return a view to render?
	if (mv != null && !mv.wasCleared()) {
		// 完成model到view的渲染,返回给前端
		render(mv, request, response);
		if (errorView) {
			WebUtils.clearErrorRequestAttributes(request);
		}
	}
	else {
		if (logger.isDebugEnabled()) {
			logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
					"': assuming HandlerAdapter completed request handling");
		}
	}

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

	if (mappedHandler != null) {
		// 调用拦截器链afterCompletion方法
		mappedHandler.triggerAfterCompletion(request, response, null);
	}
}

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

	View view;
	if (mv.isReference()) {
		// 根据viewName,借助viewResolver解析,获取view
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		if (view == null) {
			throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
					"' in servlet with name '" + getServletName() + "'");
		}
	}
	else {
		// No need to lookup: the ModelAndView object contains the actual View object.
		view = mv.getView();
		if (view == null) {
			throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
					"View object in servlet with name '" + getServletName() + "'");
		}
	}

	// Delegate to the View object for rendering.
	if (logger.isDebugEnabled()) {
		logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
	}
	try {
		// 将model中的键值对输出到request,利用RequestDispatcher渲染到jsp等前端页面上
		view.render(mv.getModelInternal(), request, response);
	}
	catch (Exception ex) {
		if (logger.isDebugEnabled()) {
			logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
					getServletName() + "'", ex);
		}
		throw ex;
	}
}

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
		HttpServletRequest request) throws Exception {

	for (ViewResolver viewResolver : this.viewResolvers) {
		// viewResolver确定view
		View view = viewResolver.resolveViewName(viewName, locale);
		if (view != null) {
			return view;
		}
	}
	return null;
}

/** AbstractCachingViewResolver.java(InternalResourceViewResolver.java) */
public View resolveViewName(String viewName, Locale locale) throws Exception {
	if (!isCache()) {
		return createView(viewName, locale);
	}
	else {
		Object cacheKey = getCacheKey(viewName, locale);
		View view = this.viewAccessCache.get(cacheKey);
		if (view == null) {
			synchronized (this.viewCreationCache) {
				view = this.viewCreationCache.get(cacheKey);
				if (view == null) {
					// 创建view
					view = createView(viewName, locale);
					if (view == null && this.cacheUnresolved) {
						view = UNRESOLVED_VIEW;
					}
					if (view != null) {
						// 缓存view
						this.viewAccessCache.put(cacheKey, view);
						this.viewCreationCache.put(cacheKey, view);
						if (logger.isTraceEnabled()) {
							logger.trace("Cached view [" + cacheKey + "]");
						}
					}
				}
			}
		}
		return (view != UNRESOLVED_VIEW ? view : null);
	}
}

/** UrlBasedViewResolver.java(InternalResourceViewResolver.java) */
protected View createView(String viewName, Locale locale) throws Exception {
	// If this resolver is not supposed to handle the given view,
	// return null to pass on to the next resolver in the chain.
	if (!canHandle(viewName, locale)) {
		return null;
	}
	// viewName前缀为"redirect:",创建RedirectView
	if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
		String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
		RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
		return applyLifecycleMethods(viewName, view);
	}
	// viewName前缀为"forward:",创建InternalResourceView
	if (viewName.startsWith(FORWARD_URL_PREFIX)) {
		String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
		return new InternalResourceView(forwardUrl);
	}
	// 直接创建View
	return super.createView(viewName, locale);
}

protected View loadView(String viewName, Locale locale) throws Exception {
	// 创建view
	AbstractUrlBasedView view = buildView(viewName);
	// 初始化view bean
	View result = applyLifecycleMethods(viewName, view);
	return (view.checkResource(locale) ? result : null);
}

private View applyLifecycleMethods(String viewName, AbstractView view) {
	return (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
}

/** InternalResourceViewResolver.java */
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
	InternalResourceView view = (InternalResourceView) super.buildView(viewName);
	if (this.alwaysInclude != null) {
		view.setAlwaysInclude(this.alwaysInclude);
	}
	if (this.exposeContextBeansAsAttributes != null) {
		view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes);
	}
	if (this.exposedContextBeanNames != null) {
		view.setExposedContextBeanNames(this.exposedContextBeanNames);
	}
	view.setPreventDispatchLoop(true);
	return view;
}

/** UrlBasedViewResolver.java(InternalResourceViewResolver.java) */
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
	// 用反射实例化view
	AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
	// 设置view对应的url,例如/WEB-INF/pages/index.jsp
	view.setUrl(getPrefix() + viewName + getSuffix());
	String contentType = getContentType();
	if (contentType != null) {
		view.setContentType(contentType);
	}
	view.setRequestContextAttribute(getRequestContextAttribute());
	view.setAttributesMap(getAttributesMap());
	if (this.exposePathVariables != null) {
		view.setExposePathVariables(exposePathVariables);
	}
	return view;
}

/** AbstractView.java(JstlView.java) */
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
	if (logger.isTraceEnabled()) {
		logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
			" and static attributes " + this.staticAttributes);
	}

	// 合并model中的键值对
	Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
	prepareResponse(request, response);
	renderMergedOutputModel(mergedModel, request, response);
}

protected Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request,
		HttpServletResponse response) {

	@SuppressWarnings("unchecked")
	Map<String, Object> pathVars = (this.exposePathVariables ?
		(Map<String, Object>) request.getAttribute(View.PATH_VARIABLES) : null);

	// Consolidate static and dynamic model attributes.
	int size = this.staticAttributes.size();
	size += (model != null) ? model.size() : 0;
	size += (pathVars != null) ? pathVars.size() : 0;
	Map<String, Object> mergedModel = new LinkedHashMap<String, Object>(size);
	mergedModel.putAll(this.staticAttributes);
	if (pathVars != null) {
		mergedModel.putAll(pathVars);
	}
	if (model != null) {
		mergedModel.putAll(model);
	}

	// Expose RequestContext?
	if (this.requestContextAttribute != null) {
		mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));
	}

	return mergedModel;
}

/** InternalResourceView.java(JstlView.java) */
protected void renderMergedOutputModel(
		Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

	// Determine which request handle to expose to the RequestDispatcher.
	HttpServletRequest requestToExpose = getRequestToExpose(request);

	// 将model中的键值对输出到request,做为request的Attribute
	exposeModelAsRequestAttributes(model, requestToExpose);

	// 在request属性中设置LocalizationContext键值对
	exposeHelpers(requestToExpose);

	// 确定request dispatcher的url
	String dispatcherPath = prepareForRendering(requestToExpose, response);

	// 获取RequestDispatcher
	RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
	if (rd == null) {
		throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
				"]: Check that the corresponding file exists within your web application archive!");
	}

	// 完成model到view的渲染,返回给前端
	// If already included or response already committed, perform include, else forward.
	if (useInclude(requestToExpose, response)) {
		response.setContentType(getContentType());
		if (logger.isDebugEnabled()) {
			logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		rd.include(requestToExpose, response);
	}

	else {
		// Note: The forwarded resource is supposed to determine the content type itself.
		exposeForwardRequestAttributes(requestToExpose);
		if (logger.isDebugEnabled()) {
			logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		rd.forward(requestToExpose, response);
	}
}

/** AbstractView.java(JstlView.java) */
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
	for (Map.Entry<String, Object> entry : model.entrySet()) {
		String modelName = entry.getKey();
		Object modelValue = entry.getValue();
		if (modelValue != null) {
			request.setAttribute(modelName, modelValue);
			if (logger.isDebugEnabled()) {
				logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
						"] to request in view with name '" + getBeanName() + "'");
			}
		}
		else {
			request.removeAttribute(modelName);
			if (logger.isDebugEnabled()) {
				logger.debug("Removed model object '" + modelName +
						"' from request in view with name '" + getBeanName() + "'");
			}
		}
	}
}

/** InternalResourceView.java(JstlView.java) */
protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response)
		throws Exception {

	String path = getUrl();
	if (this.preventDispatchLoop) {
		String uri = request.getRequestURI();
		if (path.startsWith("/") ? uri.equals(path) : uri.equals(StringUtils.applyRelativePath(uri, path))) {
			throw new ServletException("Circular view path [" + path + "]: would dispatch back " +
					"to the current handler URL [" + uri + "] again. Check your ViewResolver setup! " +
					"(Hint: This may be the result of an unspecified view, due to default view name generation.)");
		}
	}
	return path;
}

protected RequestDispatcher getRequestDispatcher(HttpServletRequest request, String path) {
	return request.getRequestDispatcher(path);
}

参考

http://jinnianshilongnian.iteye.com/blog/1594806

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值