在之前的博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMethodMapping的父类AbstractHandlerMapping,其定义了抽象方法getHandlerInternal(HttpServletRequest request),我看一下其在AbstractHandlerMethodMapping中的实现。

在AbstractHandlerMethodMapping中getHandlerInternal的实现如下:

//根据request来获取HandlerMethod
	@Override
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		//获取请求连接
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		if (logger.isDebugEnabled()) {
			logger.debug("Looking up handler method for path " + lookupPath);
		}
		//读锁
		this.mappingRegistry.acquireReadLock();
		try {
			//获取HandlerMethod
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			if (logger.isDebugEnabled()) {
				if (handlerMethod != null) {
					logger.debug("Returning handler method [" + handlerMethod + "]");
				}
				else {
					logger.debug("Did not find handler method for [" + lookupPath + "]");
				}
			}
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

具体的实现是在lookupHandlerMethod中,最终是在mappingRegistry中获取HandlerMethod,mappingRegistry可以看似是一个Map结构(其实其包含了3个map),包含了url和HandlerMethod的对应关系。

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<Match>();
		//从mappingRegistry中获取directPathMatches匹配关系
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}
		//最终返回HandlerMethod
		if (!matches.isEmpty()) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			Collections.sort(matches, comparator);
			if (logger.isTraceEnabled()) {
				logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
						lookupPath + "] : " + matches);
			}
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				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();
					throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
							request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
				}
			}
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

以下几个方法是在查找url和HandlerMethod的过程中一些帮助实现。

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
		for (T mapping : mappings) {
			T match = getMatchingMapping(mapping, request);
			if (match != null) {
				matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
			}
		}
	}
	//在子类中实现
	protected abstract T getMatchingMapping(T mapping, HttpServletRequest request);

	protected abstract Comparator<T> getMappingComparator(HttpServletRequest request);

	protected void handleMatch(T mapping, String lookupPath, HttpServletRequest request) {
		request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath);
	}
	//在子类中实现
	protected HandlerMethod handleNoMatch(Set<T> mappings, String lookupPath, HttpServletRequest request)
			throws Exception {

		return null;
	}

springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)的更多相关文章

  1. springMVC源码分析--AbstractHandlerMethodMapping注册url和HandlerMethod对应关系(十一)

    在上一篇博客springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)中我们简单地介绍了获取url和HandlerMet ...

  2. springMVC源码分析--DispatcherServlet请求获取及处理

    在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...

  3. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

  4. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  5. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  6. springMVC源码分析--ControllerClassNameHandlerMapping(九)

    在上一篇博客springMVC源码分析--AbstractControllerUrlHandlerMapping(六)中我们介绍到AbstractControllerUrlHandlerMapping ...

  7. springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)

    上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...

  8. springMVC源码分析--SimpleUrlHandlerMapping(四)

    上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...

  9. springMVC源码分析--AbstractUrlHandlerMapping(三)

    上一篇博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMapping了,接下来我们介绍其子类AbstractUrlHand ...

随机推荐

  1. 众说纷纭的ul、ol、li

    (1)提到ul ol li,大家都知道,就是三个列表标签,ul表示无需列表(unordered list),ol表示有序列表(oredr list), li 表示列表项(list item),之前我也 ...

  2. LoadRunner菜鸟入门学习笔记

    一.LR版本及浏览器选择 1.首先百度了一下LR各版本的浏览器兼容性 8.0 最高ie6 8.1 最高ie6 9.0 最高ie7 9.5 最高ie8 11.0 最高ie9( win7 32位+LR11 ...

  3. 谈一谈泛型(Generic)

    谈一谈泛型 首先,泛型是C#2出现的.这也是C#2一个重要的新特性.泛型的好处之一就是在编译时执行更多的检查. 泛型类型和类型参数 ​ 泛型的两种形式:泛型类型( 包括类.接口.委托和结构 没有泛型枚 ...

  4. 【LSGDOJ 1351】关灯

    题目描述 多瑞卡得到了一份有趣而高薪的工作.每天早晨他必须关掉他所在村庄的街灯.所有的街灯都被设置在一条直路的同一侧. 多瑞卡每晚到早晨 5 点钟都在晚会上,然后他开始关灯.开始时,他站在某一盏路灯的 ...

  5. 2015 多校联赛 ——HDU5371(manacher + 枚举)

    Sample Input 1 10 2 3 4 4 3 2 2 3 4 4   Sample Output Case #1: 9 要求找出一段数字. 将其分成3部分,第①和第②部分成回文字串,第②和第 ...

  6. [HZOI 2016]公路修建

    [题目描述] OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨 ...

  7. 探索C++多态和实现机理

    前一段时间被问到过一个问题,当时模模糊糊,就是说不清楚,问题问到说:什么情况下会将基类的析构函数定义成虚函数? 当时想到 如果子类B继承了父类A,那么定义出一个子类对象b,析构时,调用完子类析构函数, ...

  8. 最近i学习微信卡券中的会员卡功能,弄清楚不容易 ,分享一下。

    创建会员卡接口 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283 [4.1 创建会员卡接口] { " ...

  9. 容器化分布式日志组件ExceptionLess的Angular前端UI

    写在前面 随着微服务架构的流行,日志也需要由专门的分布式日志组件来完成这个工作,我们项目使用的是 ExceptionLess 这个组件,它是前后端分离的:这篇文章我们就来实践容器化 Exception ...

  10. Linux下用程序实现统计cpu和内存的利用率

    Linux下没有直接可以调用系统函数知道CPU占用和内存占用.那么如何知道CPU和内存信息呢.只有通过proc伪文件系统来实现. proc伪文件就不介绍了,只说其中4个文件.一个是/proc/stat ...