1. 类图分析
用来处理@Controller类型handler请求的HandlerMapping, 类图如下:
- ServletContextAware
作用是通过ServletContextAwareProcessor(BeanPostProcessor)注入ServletContext
public interface ServletContextAware extends Aware {
void setServletContext(ServletContext var1);
}
- ApplicationContextAware
注入ApplicationContext同时作为初始化时收集@RequestMapping信息和HandlerInterceptors的入口
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext var1) throws BeansException;
}
- HandlerMapping
用来处理具体请求, 其中HandlerExecutionChain包含Handler和Interceptor链, 每次请求生成的HandlerExecutionChain不一样
public interface HandlerMapping {
HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}
2. 启动初始化
- ServletContextAware初始化
作用比较简单, 重点关注下ServletContextAware是因为ServletContextAwareProcessor(BeanPostProcessor)而被初始化, 而ServletContextAwareProcessor是在AbstractRefreshableWebApplicationContext中定义并注入到容器中
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
//注册request/session/globalSession等scope相关组件到Mvc容器
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
//将servlet相关组件注册到Mvc容器
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
- ApplicationContextAware初始化
参考下面的流程图, 具体可以去看源码, 不再赘述.
其中重点关注: 初始化时如何处理@Controller和@RequestMapping元信息, 以及收集HandlerIntercetors信息
3. 处理请求
HandlerMapping参与DispatcherServlet的doDispach流程, 主要包括:
- 根据request获取对应的Handler处理器(即@Controller)
其中包含校验@RequestMapping中的定义的method/headers/params的check
public @interface RequestMapping {
String[] value() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
//略
}
- 获取当前request的HandlerInterceptors过滤器链
3.1 获取Handler
只要有一个满足条件的Handler, 不再进行匹配, 源码如下:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator i$ = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if (!i$.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)i$.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
由于初始化时收集了url到Handler的映射handlerMap, 所以直接精确匹配或根据URL匹配最佳的urlPattern, 再获得Handler, 源码如下:
public abstract class AbstractUrlHandlerMapping{
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
if (handler instanceof String) {
String handlerName = (String)handler;
handler = this.getApplicationContext().getBean(handlerName);
}
this.validateHandler(handler, request);
return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);
} else {
List<String> matchingPatterns = new ArrayList();
Iterator i$ = this.handlerMap.keySet().iterator();
while(i$.hasNext()) {
String registeredPattern = (String)i$.next();
if (this.getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
}
String bestPatternMatch = null;
Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
Collections.sort(matchingPatterns, patternComparator);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestPatternMatch = (String)matchingPatterns.get(0);
}
if (bestPatternMatch != null) {
handler = this.handlerMap.get(bestPatternMatch);
String pathWithinMapping;
if (handler instanceof String) {
pathWithinMapping = (String)handler;
handler = this.getApplicationContext().getBean(pathWithinMapping);
}
this.validateHandler(handler, request);
pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
Map<String, String> uriTemplateVariables = new LinkedHashMap();
Iterator i$ = matchingPatterns.iterator();
while(i$.hasNext()) {
String matchingPattern = (String)i$.next();
if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
} else {
return null;
}
}
}
}
3.2 获取HandlerInterceptors过滤链
获取Handler后, 再获取过滤器链, 最终过滤器链 = (所有adaptedInterceptors过滤器 + 根据url命中的mappedInterceptor过滤器链) , 代码如下. 详细请参考另一篇文章: HandlerInterceptor过滤器详细分析
public abstract class AbstractHandlerMapping{
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
chain.addInterceptors(this.getAdaptedInterceptors());
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator i$ = this.mappedInterceptors.iterator();
while(i$.hasNext()) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)i$.next();
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
}