SpringMVC源码解析系列3-HandleMapping

1,461 阅读2分钟

接口定义

/**
 * Interface to be implemented by objects that define a mapping between
 * requests and handler objects.
 */
public interface HandlerMapping {
  //根据request获取处理链
   HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

接口实现

以RequestMappingHandlerMapping为例来讲

RequestMappingHandlerMapping初始化过程

定义: 请求路径-处理过程映射管理

打个比方就是根据你的http请求的路径得到可以处理的handler(你的Controller方法)

先看下他的继承关系

RequestMappingHandlerMapping

看到3个Spring的生命周期接口

  1. ServletContextAware:保存ServletContext

    #org.springframework.web.context.support.WebApplicationObjectSupport
    @Override
    public final void setServletContext(ServletContext servletContext) {
    	if (servletContext != this.servletContext) {
    		//保存ServletContext
    		this.servletContext = servletContext;
    		if (servletContext != null) {
    			//空实现
    			initServletContext(servletContext);
    		}
    	}
    }
    
  2. ApplicationContext:保存Spring上下文

    @Override
    public final void setApplicationContext(ApplicationContext context) throws BeansException {
    ...
      //保存SpringMVC上下文
      this.applicationContext = context;
      //保存资源访问器
      this.messageSourceAccessor = new MessageSourceAccessor(context);
      //空实现
      initApplicationContext(context);
    	...
    }
    
  3. InitlizingBean:初始化映射关系

    #org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
    //1.
    @Override
    public void afterPropertiesSet() {
       if (this.useRegisteredSuffixPatternMatch) {
          this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
       }
       super.afterPropertiesSet();
    }
    //4.
    @Override
    protected boolean isHandler(Class<?> beanType) {
    	return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
    			(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
    }
    //6.
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
    	RequestMappingInfo info = null;
    	RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
    	if (methodAnnotation != null) {
    		//组装映射信息
    		RequestCondition<?> methodCondition = getCustomMethodCondition(method);
    		info = createRequestMappingInfo(methodAnnotation, methodCondition);
    		RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
    		if (typeAnnotation != null) {
    			RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
    			info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
    		}
    	}
    	return info;
    }
    #org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
    //2.
    @Override
    public void afterPropertiesSet() {
    	initHandlerMethods();
    }
    //3.
    protected void initHandlerMethods() {
    	if (logger.isDebugEnabled()) {
    		logger.debug("Looking for request mappings in application context: " + getApplicationContext());
    	}
    	//从容器中获取所有object类型名
    	String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
    			BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
    			getApplicationContext().getBeanNamesForType(Object.class));
    	for (String beanName : beanNames) {
    		//抽象,过滤(在RequestMappingHandlerMapping中根据Controller和RequestMapping注解过滤)
    		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
    				isHandler(getApplicationContext().getType(beanName))){
    			//探测类中定义的handler方法
    			detectHandlerMethods(beanName);
    		}
    	}
    	handlerMethodsInitialized(getHandlerMethods());
    }
    //5.
    protected void detectHandlerMethods(final Object handler) {
    	Class<?> handlerType =
    			(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
    	final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
    	final Class<?> userType = ClassUtils.getUserClass(handlerType);
    	//得到符合条件的handler方法
    	Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
    		@Override
    		public boolean matches(Method method) {
    			//抽象,得到映射信息(如RequestMappingInfo)
    			T mapping = getMappingForMethod(method, userType);
    			if (mapping != null) {
    				mappings.put(method, mapping);
    				return true;
    			}
    			else {
    				return false;
    			}
    		}
    	});
    	//注册handler映射关系
    	for (Method method : methods) {
    		//保存映射路径和处理方法(还有跨域信息)
    		registerHandlerMethod(handler, method, mappings.get(method));
    	}
    }
    

过程概括:

  1. 获取所有object子类

  2. 根据条件过滤出handle处理类

  3. 解析handle类中定义的处理方法

  4. 注册映射关系

    public void register(T mapping, Object handler, Method method) {
    			try {
      	//保存handler和处理方法
    	HandlerMethod handlerMethod = createHandlerMethod(handler, method);
    	...
         //保存映射路径和HandlerMethod
    	this.mappingLookup.put(mapping, handlerMethod);
    	//解析@CrossOrigin配置(跨域用)
    	CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
      	//保存跨域信息
    	if (corsConfig != null) {
    		this.corsLookup.put(handlerMethod, corsConfig);
    	}
    	//保存映射关系
    	this.registry.put(mapping, new MappingRegistration<T>(mapping, handlerMethod, directUrls, name));
    }
    ...
    

}


## getHandler()实现

```java
#org.springframework.web.servlet.handler.AbstractHandlerMapping
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//抽象,调用子类实现得到一个handler(可以是任一对象,需要通过HandleAdapter来解析)
//RequestMappingInfoHandlerMapping中具体实现就是匹配请求路径和RequestMapping注解
Object handler = getHandlerInternal(request);
...
//包装handle成HandlerExecutionChain
 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
 //如果是跨域请求 则根据@CrossOrigin配置添加前置Intercept
 if (CorsUtils.isCorsRequest(request)) {
 	CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
 	CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
 	CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
 	executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
 }
 return executionChain;
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
@Override
 protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
 //得到映射路径
 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
 ...
 try {
 	//根据映射路径获取HandlerMethod
 	HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
 	return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
 }
 ...
}