spring boot MVC 流程简单梳理

web应用收到请求时,会把请求打到

org.springframework.web.servlet.DispatcherServlet#doDispatch

MVC的流程,也就是 doDispatch 方法的流程

查找Handler

mappedHandler = getHandler(processedRequest);  

查找HandlerAdapter

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

执行handler

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

结果处理

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 

在查找handler这一步,是怎么做的呢?

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

 

实际上就是 遍历 List列表 ,而列表的初始化,是在 Servlet第一次加载的init中完成的。也就是在DispatcherServlet 父类 HttpServletBean 中的init触发调用的,最终会调到

org.springframework.web.servlet.DispatcherServlet#initHandlerMappings

private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			Map matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}

代码注释的非常清楚:

// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// Ensure we have at least one HandlerMapping, by registering a default HandlerMapping if no other mappings are found.

首先从容器中获取,容器中没有获取到时,再从配置文件中获取。可以参考DispatcherServlet.properties文件中的配置。

spring boot 项目,在spring-boot-autoconfigure中完成了 HandlerMapping的加载。

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

所以,在容器启动之后,容器中已经加载了 默认的 

org.springframework.web.servlet.HandlerMapping

对于

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

在实例化后,会调用

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet 

这个方法会把容器中的handler提取出来

protected boolean isHandler(Class beanType) {
		return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
				AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
	}

找到handler后,再把handler的 所有 mapper方法找到,包装成 

RequestMappingInfo,最后 注册到 
private final MultiValueMap urlLookup = new LinkedMultiValueMap<>();

key 是 url,value 是 RequestMappingInfo

 这些准备工作做完之后,第一步的 查找 Handler 才能完成。而这些准备工作,也是在应用启动时完成的。

查找HandlerAdapter,和 查找Handler类似。

到这里,MVC基本逻辑就清楚了。首先是 容器启动,把Handler 和 url 之间的映射 加载好。当请求进来时,根据url 找到 hanlder。找到之后 执行就可以了。当然,对应hander,有两个扩展点

org.springframework.web.servlet.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;
	}

org.springframework.web.servlet.HandlerExecutionChain#applyPostHandle 

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable 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);
			}
		}
	}

 

可以看到,在执行 handler之前 和之后 会 执行 

org.springframework.web.servlet.HandlerInterceptor

 

这就是 拦截器的执行时机。

(未完)

 

 

你可能感兴趣的:(笔记,spring系列,mvc,spring,boot,spring)