HandlerMapping组件分析
HandlerMapping继承结构
可以看到AbstractHandlerMapping分为两只:一只继承AbstractUrlHandlerMapping,一只继承与AbstractHandlerMethodMapping。
AbstractHandlerMapping是handlerMapping的抽象实现。AbstractHandlerMapping采用模板方法模式HandlerMapping实现了整体架构,字类只需要通过模板方法提供一些初始值或具体的算法即可。获取handler的方法通过模板方法getHandlerInternal交给了字类。AbstractHandlerMapping中保存了所用配置的interceptors。
AbstractHandlerMapping继承了WebApplicationObjectSupport,初始化时会调用initApplicationContext方法。
AbstractHandlerMapping系列
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
//默认的handler
@Nullable
private Object defaultHandler;
//url匹配工具类
private UrlPathHelper urlPathHelper = new UrlPathHelper();
//正则匹配对象
private PathMatcher pathMatcher = new AntPathMatcher();
private final List<Object> interceptors = new ArrayList<>();
private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();
private CorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
private CorsProcessor corsProcessor = new DefaultCorsProcessor();
private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
@Nullable
private String beanName;
protected void initApplicationContext() throws BeansException {
//给子类提供一个修改或添加interceptors的方法
extendInterceptors(this.interceptors);
//将容器中所有类型的MappedInterceptor添加到adaptedInterceptors中
detectMappedInterceptors(this.adaptedInterceptors);
//初始化interceptors,将符合的interceptor转换成HandlerInterceptor类型,添加到adaptedInterceptors中
initInterceptors();
}
//初始化Interceptor
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
//获取HandlerExecutionChain链对象
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//模板方法字类实现 获取handler
Object handler = getHandlerInternal(request);
//为空就获取默认的handler
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// 判断是否为字符串,是字符串通过beanNames从容器中获取对象
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//获取拦截器链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//判断handler是不是HandlerExecutionChain 类型,不是则创建一个
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//获取请求路径
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
//遍历adaptedInterceptors,然后将MappedInterceptor进行匹配进行加入,其它类型则直接加入
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
}
AbstractUrlHandlerMapping系列
AbstractUrlHandlerMapping从名字上面来可以看出他是通过url来进行匹配的,是将url和对应的handler保存在一个map中。在getHandlerInternal中使用handlerMap来进行handler获取。另外还定义了处理"/"的handler。
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {
//根路径处理handler
@Nullable
private Object rootHandler;
private boolean useTrailingSlashMatch = false;
//懒加载handler
private boolean lazyInitHandlers = false;
//url和handler映射
private final Map<String, Object> handlerMap = new LinkedHashMap<>();
//获取handler
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//获取url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//获取处理器
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
Object rawHandler = null;
//判断是否用根处理器
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
//判断是否用默认处理器,在父类定义了
if (rawHandler == null) {
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
//判断为字符串,从容器中获取
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = obtainApplicationContext().getBean(handlerName);
}
//模板方法,验证handler和request是否匹配
validateHandler(rawHandler, request);
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
//直接用字符串匹配 主要匹配是通过handlerMap 进行匹配,下面会讲到handlerMap的初始化过程
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
//如果是string从容器中获取
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//验证是否合法
validateHandler(handler, request);
//返回拦截器链
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
List<String> matchingPatterns = new ArrayList<>();
//通过正则匹配路径 比如 * 和url匹配
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
//使用尾随斜杠匹配
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern +"/");
}
}
}
String bestMatch = null;
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
//查询的handler进行排序
matchingPatterns.sort(patternComparator);
if (logger.isTraceEnabled() && matchingPatterns.size() > 1) {
logger.trace("Matching patterns " + matchingPatterns);
}
bestMatch = matchingPatterns.get(0);
}
if (bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
if (handler == null) {
if (bestMatch.endsWith("/")) {
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
}
if (handler == null) {
throw new IllegalStateException(
"Could not find handler for best pattern match [" + bestMatch + "]");
}
}
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (logger.isTraceEnabled() && uriTemplateVariables.size() > 0) {
logger.trace("URI variables " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}
// 找不到返回null
return null;
}
//创建拦截器链
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {
HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
//添加两个拦截器
chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
}
return chain;
}
**下面讲解handlerMap的初始化,它通过registerHandler方法进行,不过和之前创建的不同是,这里的registerHandler方法是通过子类调用。这样不同的子类可以通过不同的方式注册handlerMap。**
//注册多个url到容器
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
Assert.notNull(urlPaths, "URL path array must not be null");
for (String urlPath : urlPaths) {
registerHandler(urlPath, beanName);
}
}
//注册一个url到容器
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// 没设置懒加载并且是string类型 ,则从从其获取bean.
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
Object mappedHandler = this.handlerMap.get(urlPath);
//如果已存在并不相等则报错
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
//如果已存在并等于"/"设置到rootHadler
else {
if (urlPath.equals("/")) {
if (logger.isTraceEnabled()) {
logger.trace("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
//如果已存在并等于"/*"设置到DefaultHandler
else if (urlPath.equals("/*")) {
if (logger.isTraceEnabled()) {
logger.trace("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
//没有找到则put进去
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isTraceEnabled()) {
logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}
}
SimpleUrlHandlerMapping系列
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
private final Map<String, Object> urlMap = new LinkedHashMap<>();
`
//调用父类初始化
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
}
//注册handlerMap
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.trace("No patterns in " + formatMappingName());
}
else {
urlMap.forEach((url, handler) -> {
// Prepend with slash if not already present.
if (!url.startsWith("/")) {
url = "/" + url;
}
if (handler instanceof String) {
handler = ((String) handler).trim();
}
//调用父类注册
registerHandler(url, handler);
});
if (logger.isDebugEnabled()) {
List<String> patterns = new ArrayList<>();
if (getRootHandler() != null) {
patterns.add("/");
}
if (getDefaultHandler() != null) {
patterns.add("/**");
}
patterns.addAll(getHandlerMap().keySet());
logger.debug("Patterns " + patterns + " in " + formatMappingName());
}
}
}
}
AbstractDetectingUrlHandlerMapping系列
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {
//也是重写父类的initApplicationContext方法
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
ApplicationContext applicationContext = obtainApplicationContext();
//获取所有的bean
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
applicationContext.getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
//对bean解析url,模板方法,子类实现
String[] urls = determineUrlsForHandler(beanName);
//能解析就注册到父类
if (!ObjectUtils.isEmpty(urls)) {
// URL paths found: Let's consider it a handler.
registerHandler(urls, beanName);
}
}
if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
}
}
}
AbstractDetectingUrlHandlerMapping有一个子类:BeanNameUrlHandlerMapping:
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
public BeanNameUrlHandlerMapping() {
}
//对beanName进行解析
protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList();
//p判断是不是以”/“开头,是的话就当做url
if (beanName.startsWith("/")) {
urls.add(beanName);
}
String[] aliases = this.obtainApplicationContext().getAliases(beanName);
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
}
}
AbstractHandlerMethodMapping系列
从前面类图来看 AbstractHandlerMethodMapping系列有两个子类:RequestMappingInfoHandlerMapping和RequestMappingHandlerMapping,这三个类一次继承。AbstractHandlerMethodMapping系列是把Method当作handler使用,这也是我们现在用得最多的一种handler,我们经常用的@RequestMapping所注释的方法就是这种handler,他专门有一个类型HandlerMethod。
在AbstractHandlerMethodMapping类中有一个内部类(MappingRegistry),下面我们来看一下。
//在AbstractHandlerMethodMapping类中维护了一个MappingRegistry对象的引用。。
private final MappingRegistry mappingRegistry = new MappingRegistry();
/**
*一个注册表,它维护处理程序方法的所有映射,公开方法
*/
class MappingRegistry {
// 里面配置的是requestMapponig中的映射,key是RequestMappingInfo类型 ,value是MappingRegistration类型也是 AbstractHandlerMethodMapping的内部类,里面有默认配置
看一下本人debug的数据截图可能更方便理解! 里面有我们写的requestMapping和默认配置的错误页面.。
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
//里面保存着requestMappingInfo和HandlerMethod对象
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
//里面是url和匹配的requestMappingInfo对象
//里面保存着url和匹配条件,当然这里的url可以是pattern式的,也可以是通配符模式,当然这里的Map不是扑通的map,而是MultiValueMap,这种key可以对应多个值map,他的值其实是一个list对象
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
//nameLookup 保存的是name和HandlerMethod的对用关系,这里的value是一个list类型,name的生成规则是#+方法名 这个nameLookup在正常的匹配中并不会使用
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
//在getHandlerInternal方法会进行加锁
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public Map<T, HandlerMethod> getMappings() {
return this.mappingLookup;
}
@Nullable
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
public List<HandlerMethod> getHandlerMethodsByMappingName(String mappingName) {
return this.nameLookup.get(mappingName);
}
/**
* Return CORS configuration. Thread-safe for concurrent use.
*/
public CorsConfiguration getCorsConfiguration(HandlerMethod handlerMethod) {
HandlerMethod original = handlerMethod.getResolvedFromHandlerMethod();
return this.corsLookup.get(original != null ? original : handlerMethod);
}
/**
* Acquire the read lock when using getMappings and getMappingsByUrl.
*/
public void acquireReadLock() {
this.readWriteLock.readLock().lock();
}
/**
* Release the read lock after using getMappings and getMappingsByUrl.
*/
public void releaseReadLock() {
this.readWriteLock.readLock().unlock();
}
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
private List<String> getDirectUrls(T mapping) {
List<String> urls = new ArrayList<>(1);
for (String path : getMappingPathPatterns(mapping)) {
if (!getPathMatcher().isPattern(path)) {
urls.add(path);
}
}
return urls;
}
}
private static class MappingRegistration<T> {
//requestMapponigInfo对象
private final T mapping;
//HandlerMethod对象
private final HandlerMethod handlerMethod;
//url路径,从request中获取
private final List<String> directUrls;
//解析规则是 #+方法名
@Nullable
private final String mappingName;
}
介绍一下urlLookup和mappingLookup,通过urlLookup找到符合的requestMappingInfo对象,在通过mappingLookup以查询出来的mappingLookup对象找寻对用的handlermethod对象。
//从上面的代码看出,主要的解析工作都在于3个map,现在我们看一下map的初始化。
AbstractHandlerMethodMapping实现了InitializingBean接口,所以容器会自动调用 afterPropertiesSet方法,afterPropertiesSet又交给initHandlerMethods进行初始化工作。
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
//获取候选的bean
protected String[] getCandidateBeanNames() {
return (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
}
//通过beanName先获取beanType,不为空判断是不是handler,调用isHandler方法
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
if (beanType != null && isHandler(beanType)) {
//注册beanName
detectHandlerMethods(beanName);
}
}
//判断bean前是否有Controller或RequestMapping注解
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
//detectHandlerMethods方法负责将handler保存到map中
protected void detectHandlerMethods(Object handler) {
//获取handler的class
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
//如果是cglib代理子对象类型,则返回父类型,否则返回本身
Class<?> userType = ClassUtils.getUserClass(handlerType);
//获取当前bean中符合handler要求的method,
//遍历传入userType的所有方法,通过匿名getMappingForMethod方法进行匹配
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//将符合要求的数据保存起来
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
说完了找到的HandlerMethod,在看一下怎么注册进去的
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
//创建HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//验证
assertUniqueMethodMapping(handlerMethod, mapping);
//添加到mappingLookup中
this.mappingLookup.put(mapping, handlerMethod);
//添加到 urlLookup
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
//添加到 nameLookup 调用addMappingName方法
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
//把映射封装到registry中
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
private void assertUniqueMethodMapping(HandlerMethod newHandlerMethod, T mapping) {
//验证handlerMethod 是否已存在,如果已存在和现在传入的不同则抛异常
HandlerMethod handlerMethod = this.mappingLookup.get(mapping);
if (handlerMethod != null && !handlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException(
"Ambiguous mapping. Cannot map '" + newHandlerMethod.getBean() + "' method \n" +
newHandlerMethod + "\nto " + mapping + ": There is already '" +
handlerMethod.getBean() + "' bean method\n" + handlerMethod + " mapped.");
}
}
//检查是否存在,存在并且相等直接返回,不相等的话放到新的List中put进去
private void addMappingName(String name, HandlerMethod handlerMethod) {
List<HandlerMethod> oldList = this.nameLookup.get(name);
if (oldList == null) {
oldList = Collections.emptyList();
}
for (HandlerMethod current : oldList) {
if (handlerMethod.equals(current)) {
return;
}
}
List<HandlerMethod> newList = new ArrayList<>(oldList.size() + 1);
newList.addAll(oldList);
newList.add(handlerMethod);
this.nameLookup.put(name, newList);
}
通过前面的分析,这个类的主要功能是通过getHandlerInternal获取处理器,下面看一下代码:
rotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获取url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
//调用方法返回handler
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
//这个代码很简单,从urlLookup获取handler
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//将找到的加入matches
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
//如果为空的话 从mappingLookup获取所有的key添加到matches
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
//将handlerMethod放入request的BEST_MATCHING_HANDLER_ATTRIBUTE
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
//如果没有handler 在此匹配所有,查看url是否匹配,不匹配则抛出异常
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
详细的过程已经做了注释,整个过程以Match作为载体,Match是个内部类,封装了匹配条件和HandlerMethod两个属性。子类RequestMappingInfoHandlerMapping中进行了重写,将更多参数设置到request的属性,主要为了以后使用时方便。
小结:此篇详细分析的HandlerMapping的各种实现方式,HandlerMapping在AbstractHandlerMapping中设计其功能是根据request找寻handler和interceptors,组合成handlerExecutionChain类型返回。找寻handler的handlerInternal方法由子类实现,找寻interceptors则由自己实现,具体由几个map实现。
AbstractHandlerMapping系列分为两个子类:AbstractHandlerMethodMapping和AbstractUrlHandlerMapping。前者匹配的内容比较多,而且直接匹配到method,后者通过url匹配,这也是使用对多的方式。
参考资料:看透springmvc源码