/** * 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爲例來說java
定義: 請求路徑-處理過程映射管理web
打個比方就是根據你的http請求的路徑獲得能夠處理的handler(你的Controller方法)spring
先看下他的繼承關係跨域
看到3個Spring的生命週期接口bash
ServletContextAware:保存ServletContextmvc
#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);
}
}
}
複製代碼
ApplicationContext:保存Spring上下文app
@Override
public final void setApplicationContext(ApplicationContext context) throws BeansException {
...
//保存SpringMVC上下文
this.applicationContext = context;
//保存資源訪問器
this.messageSourceAccessor = new MessageSourceAccessor(context);
//空實現
initApplicationContext(context);
...
}
複製代碼
InitlizingBean:初始化映射關係cors
#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));
}
}
複製代碼
過程歸納:ide
獲取全部object子類ui
根據條件過濾出handle處理類
解析handle類中定義的處理方法
註冊映射關係
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);
}
...
}
複製代碼