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 MultiValueMapurlLookup = 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
这就是 拦截器的执行时机。
(未完)