在之前的博客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. MyBatis基础学习笔记--自总结

    一.MyBatis和jdbc的区别 jdbc的过程包括: 1.加载数据库驱动. 2.建立数据库连接. 3.编写sql语句. 4.获取Statement:(Statement.PrepareStatem ...

  2. Oracle数据库基础练习题

    --1.查询和SMITH相同部门的员工姓名和雇用日期select ename,hiredate from emp where deptno=(select deptno from emp where ...

  3. ActiveMQ笔记:一个高稳定,可扩展的的部署方案

    本文介绍一个笔者在实际工作中的实施的基于ActiveMQ的一个高稳定,可扩展的异步消息系统. ActiveMQ是一个成熟的基于Java语言的开源消息系统,在实际应用中被大量使用.ActiveMQ在系统 ...

  4. 获取Avrix上Computer Vision and Pattern Recognition的论文,进一步进行统计分析。

    此文主要记录我在18年寒假期间,收集Avrix论文的总结 寒假生活题外   在寒假期间,爸妈每天让我每天跟着他们6点起床,一起吃早点收拾,每天7点也就都收拾差不多.   早晨的时光是人最清醒的时刻,而 ...

  5. [HNOI2004]敲砖块

    题目描述 在一个凹槽中放置了 n 层砖块.最上面的一层有n 块砖,从上到下每层依次减少一块砖.每块砖 都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示. 14 15 4 3 23 33 33 7 ...

  6. 基于vfs实现自己的文件系统

    1.Linux 文件系统组成结构 linux文件系统有两个重要的特点:一个是文件系统抽象出了一个通用文件表示层--虚拟文件系统或称做VFS.另外一个重要特点就是它的文件系统支持动态安装(或说挂载等), ...

  7. Codeforces 671 D. Roads in Yusland

    题目描述 Mayor of Yusland just won the lottery and decided to spent money on something good for town. Fo ...

  8. 【Codeforces 851D Arpa and a list of numbers】

    Arpa的数列要根据GCD变成好数列. ·英文题,述大意:      给出一个长度为n(n<=5000000)的序列,其中的元素a[i]<=106,然后输入两个数x,y(x,y<=1 ...

  9. [poj1279]Art Gallery

    题意:求多边形的核的面积. 敲一下半平面交模板........  然后我wa了一早上就因为写了%lf  不知道poj什么破机制还不能用lf的,真的想跳楼 #include<iostream> ...

  10. java continue与break区别

    在循环体中跳出循环语句有continue与break语句 continue:跳出本次循环,包括本次循环continue后面的语句, break:跳出循环体,就是说一遇到break循环就结束. 代码: ...