RequestMappingHandlerMapping初始化
最近想弄清楚spring mvc的调用过程,想到怎么样根据url访问到对应的method,于是看了下spring mvc的相关源码,在此分析下。
找到 RequestMappingHandlerMapping 类,可以看到实现了InitializingBean接口。
找到 RequestMappingHandlerMapping 的afterPropertiesSet() 方法
public void afterPropertiesSet() {
this.config = new BuilderConfiguration();
this.config.setUrlPathHelper(this.getUrlPathHelper());
this.config.setPathMatcher(this.getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(this.getContentNegotiationManager());
//调用AbstractHandlerMethodMapping afterPropertiesSet()方法
super.afterPropertiesSet();
}
AbstractHandlerMethodMapping 的afterPropertiesSet()方法
public void afterPropertiesSet() {
//初始化控制层方法
this.initHandlerMethods();
}
initHandlerMethods()
protected void initHandlerMethods() {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Looking for request mappings in application context: " + this.getApplicationContext());
}
//获取spring mvc 容器注册的bean名称
String[] beanNames = this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.getApplicationContext(), Object.class) : this.getApplicationContext().getBeanNamesForType(Object.class);
String[] var2 = beanNames;
int var3 = beanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String beanName = var2[var4];
if (!beanName.startsWith("scopedTarget.")) {
Class beanType = null;
try {
beanType = this.getApplicationContext().getType(beanName);
} catch (Throwable var8) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Could not resolve target class for bean with name '" + beanName + "'", var8);
}
}
//判断controller 类是否带有@Controller 或者@RequestMapping注解
if (beanType != null && this.isHandler(beanType)) {
this.detectHandlerMethods(beanName);
}
}
}
this.handlerMethodsInitialized(this.getHandlerMethods());
}
detectHandlerMethods(Object handler)
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = handler instanceof String ? this.getApplicationContext().getType((String)handler) : handler.getClass();
final Class<?> userType = ClassUtils.getUserClass(handlerType);
//获取所有userType带有@RequestMapping注解的方法 Map<Method,RequestMappingInfo>
Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MetadataLookup<T>() {
public T inspect(Method method) {
try {
return AbstractHandlerMethodMapping.this.getMappingForMethod(method, userType);
} catch (Throwable var3) {
throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, var3);
}
}
});
if (this.logger.isDebugEnabled()) {
this.logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
}
Iterator var5 = methods.entrySet().iterator();
while(var5.hasNext()) {
Entry<Method, T> entry = (Entry)var5.next();
Method invocableMethod = AopUtils.selectInvocableMethod((Method)entry.getKey(), userType);
T mapping = entry.getValue();
//将
this.registerHandlerMethod(handler, invocableMethod, mapping);
}
}
AbstractHandlerMethodMapping内部类MappingRegistry,这个是核心类,所有的路径相关信息全部存放在MappingRegistry中。
registry:key为RequestMapping,value为MappingRegistration;
mappingLookup:key为RequestMapping,value为HandlerMethod;
urlLookup:key为url,value为RequestMappingInfo;
nameLookup:key为mappingName,value为List;
corsLookup:key为HandlerMethod,value为CorsConfiguration;
class MappingRegistry {
//(RequestMappingInfo,MappingRegistration)
private final Map<T, AbstractHandlerMethodMapping.MappingRegistration<T>> registry = new HashMap();
// (RequestMappingInfo,HandlerMethod)
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap();
// (url,RequestMappingInfo)
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap();
//(mappingName,List<HandlerMethod>)
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap();
//跨域信息(HandlerMethod,CorsConfiguration)
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap();
//读写锁
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}
AbstractHandlerMethodMapping内部类MappingRegistration
private static class MappingRegistration<T> {
//RequestMappingInfo
private final T mapping;
//HandlerMethod
private final HandlerMethod handlerMethod;
//requestMapping路径 /user/create
private final List<String> directUrls;
//例如类名为UserController的create方法, 则mappingName 为 UC#create , UC为类名的大写字母
private final String mappingName;
public MappingRegistration(T mapping, HandlerMethod handlerMethod, List<String> directUrls, String mappingName) {
Assert.notNull(mapping, "Mapping must not be null");
Assert.notNull(handlerMethod, "HandlerMethod must not be null");
this.mapping = mapping;
this.handlerMethod = handlerMethod;
this.directUrls = directUrls != null ? directUrls : Collections.emptyList();
this.mappingName = mappingName;
}
}
registerHandlerMethod(Object handler, Method method, T mapping)
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
mappingRegistry 的 register(T mapping, Object handler, Method method)
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
//构造HandlerMethod
HandlerMethod handlerMethod = AbstractHandlerMethodMapping.this.createHandlerMethod(handler, method);
//校验 mappingLookup 是否已经存在key为mapping的记录,也就是校验是否存在两个相同的url
this.assertUniqueMethodMapping(handlerMethod, mapping);
if (AbstractHandlerMethodMapping.this.logger.isInfoEnabled()) {
AbstractHandlerMethodMapping.this.logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
//**mappingLookup存放(RequestMappingInfo,HandlerMethod)**
this.mappingLookup.put(mapping, handlerMethod);
// url 例如: /user/create
List<String> directUrls = this.getDirectUrls(mapping);
Iterator var6 = directUrls.iterator();
while(var6.hasNext()) {
String url = (String)var6.next();
// **urlLookup (url,RequestMappingInfo)**
this.urlLookup.add(url, mapping);
}
String name = null;
if (AbstractHandlerMethodMapping.this.getNamingStrategy() != null) {
name = AbstractHandlerMethodMapping.this.getNamingStrategy().getName(handlerMethod, mapping);
// **nameLookup (name,List<HandlerMethod>)**
this.addMappingName(name, handlerMethod);
}
// Cors 跨域访问的处理
CorsConfiguration corsConfig = AbstractHandlerMethodMapping.this.initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
//**corsLookup(HandlerMethod,CorsConfiguration)**
this.corsLookup.put(handlerMethod, corsConfig);
}
//**registry (RequestMappingInfo,MappingRegistration)**
this.registry.put(mapping, new AbstractHandlerMethodMapping.MappingRegistration(mapping, handlerMethod, directUrls, name));
} finally {
this.readWriteLock.writeLock().unlock();
}
}
FrameworkServlet 类有一个监听器内部类
//在初始化容器时,AbstractApplicationContext 的refresh()方法里,调用 finishRefresh()方法,
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
private ContextRefreshListener() {
}
public void onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.this.onApplicationEvent(event);
}
}
public void onApplicationEvent(ContextRefreshedEvent event) {
this.refreshEventReceived = true;
this.onRefresh(event.getApplicationContext());
}
**
spring mvc 处理过程
**
DispatcherServlet是spring mvc 前端控制器,是spring mvc的核心类,其继承关系图如下所示。
tomcat 启动时,会调用init()方法初始化spring mvc容器,其初始化容器过程,和初始化spring 容器类似,最终都是调用AbstractApplicationContext 的 refresh()方法,具体过程可以参考:https://mp.csdn.net/mdeditor/89609303
访问路径会调用doService方法
doService(HttpServletRequest request, HttpServletResponse response)
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (this.logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();
label108:
while(true) {
String attrName;
do {
if (!attrNames.hasMoreElements()) {
break label108;
}
attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
/**
* 设置request attribute属性
*/
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
//spring mvc 工作处理过程
this.doDispatch(request, response);
} finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
doDispatch(HttpServletRequest request, HttpServletResponse response)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
//校验请求contentType是否为multipart/**
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//根据url 从
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.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 (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
//拦截器preHandle处理,如果有一个拦截器的preHandle()方法返回为false,则直接返回退出
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//处理@RequestMapping的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//设置默认视图名称
this.applyDefaultViewName(processedRequest, mv);
//处理拦截器postHandle方法,返回ModelAndView
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
//异常处理
//视图解析
// 处理拦截器afterCompletion方法
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取所有的拦截器
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
//按照顺序调用拦截器preHandle方法,并且记录interceptorIndex,
//只要返回值为false,则调用 triggerAfterCompletion()方法,也就是调用拦截器的afterCompletion()方法
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
//逆向调用拦截器postHandle方法
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
//从preHandle()返回false的那个拦截器的interceptorIndex,逆向调用afterCompletion()方法
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
}
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) {
this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException)exception).getModelAndView();
} else {
Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
mv = this.processHandlerException(request, response, handler, exception);
errorView = mv != null;
}
}
if (mv != null && !mv.wasCleared()) {
this.render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
}
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}