上一篇博客springMVC源码分析--HandlerMapping(一)中我们简单的介绍了HandlerMapping,接下来我们介绍一下它的抽象实现类AbstractHandlerMapping

HandlerMapping中定义了方法getHandler(HttpServletRequest request),AbstractHandlerMapping中的实现如下:

//获得一个HandlerExecutionChain
	@Override
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//从实现类中获得HanlderMethod
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);
		}
		//获得HandlerExecutionChain
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		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;
	}

在getHandler方法中又出现了两个方法getHandlerInternal(request),在子类中实现,目的就是获取要执行的Controller。

//模板方法,用于子类中实现,通过request去查找对应的执行方法HandlerMethod
	protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

getHandlerExecutionChain就是创建一个HandlerExecutionChain实例,参数值就是handler和request。

//
	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		//如果没有获得则创建一个
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
		//获得IP地址及端口后的URL地址
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		//在HandlerExecutionChain中添加拦截器
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				//根据lookupPath来获取Interceptor
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

AbstractHandlerMapping提供了设置不同HandlerMapping的执行顺序oder。

//设置不同HandlerMapping实现类的执行顺序
	public final void setOrder(int order) {
	  this.order = order;
	}

	@Override
	public final int getOrder() {
	  return this.order;
	}

除了以上几个重要的方法外,AbstractHandlerMapping还提供了进行拦截器初始化的一些操作。

//初始化时调用,初始化一些基本信息,这里主要是初始化一些拦截器
	@Override
	protected void initApplicationContext() throws BeansException {
		extendInterceptors(this.interceptors);//添加或修车intercept,现在并没有具体实现
		detectMappedInterceptors(this.adaptedInterceptors);//将springMVC容器或者父容器中的所有MappedInterceptor类型的Bean添加到mappedInterceptors属性中
		initInterceptors();
	}

	protected void extendInterceptors(List<Object> interceptors) {
	}

	//将springMVC容器或者父容器中的所有MappedInterceptor类型的Bean添加到mappedInterceptors属性中
	protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
		mappedInterceptors.addAll(
				BeanFactoryUtils.beansOfTypeIncludingAncestors(
						getApplicationContext(), MappedInterceptor.class, true, false).values());
	}

	//初始化Interceptor,将interceptors属性里所包含的对象按类型添加到mappedInterceptors或者adaptedInterceptors中。
	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));
			}
		}
	}

	protected HandlerInterceptor adaptInterceptor(Object interceptor) {
		if (interceptor instanceof HandlerInterceptor) {
			return (HandlerInterceptor) interceptor;
		}
		else if (interceptor instanceof WebRequestInterceptor) {
			return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
		}
		else {
			throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
		}
	}

	protected final HandlerInterceptor[] getAdaptedInterceptors() {
		int count = this.adaptedInterceptors.size();
		return (count > 0 ? this.adaptedInterceptors.toArray(new HandlerInterceptor[count]) : null);
	}

	protected final MappedInterceptor[] getMappedInterceptors() {
		List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				mappedInterceptors.add((MappedInterceptor) interceptor);
			}
		}
		int count = mappedInterceptors.size();
		return (count > 0 ? mappedInterceptors.toArray(new MappedInterceptor[count]) : null);
	}

总体来看AbstractHandlerMapping提供了抽象方法getHandlerInternal在子类中实现,根据获得的Handler及配置的拦截器Interceptor来生成HandlerExecutionChain。

完整的AbstractHandlerMapping源码如下:

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
		implements HandlerMapping, Ordered {

	private int order = Integer.MAX_VALUE;  // default: same as non-Ordered

	private Object defaultHandler;

	private UrlPathHelper urlPathHelper = new UrlPathHelper();

	private PathMatcher pathMatcher = new AntPathMatcher();

	private final List<Object> interceptors = new ArrayList<Object>();

	private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<HandlerInterceptor>();

	private CorsProcessor corsProcessor = new DefaultCorsProcessor();

	private final UrlBasedCorsConfigurationSource corsConfigSource = new UrlBasedCorsConfigurationSource();

	//设置不同HandlerMapping实现类的执行顺序
	public final void setOrder(int order) {
	  this.order = order;
	}

	@Override
	public final int getOrder() {
	  return this.order;
	}

	public void setDefaultHandler(Object defaultHandler) {
		this.defaultHandler = defaultHandler;
	}

	public Object getDefaultHandler() {
		return this.defaultHandler;
	}

	public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
		this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
		this.corsConfigSource.setAlwaysUseFullPath(alwaysUseFullPath);
	}

	public void setUrlDecode(boolean urlDecode) {
		this.urlPathHelper.setUrlDecode(urlDecode);
		this.corsConfigSource.setUrlDecode(urlDecode);
	}

	public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
		this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
		this.corsConfigSource.setRemoveSemicolonContent(removeSemicolonContent);
	}

	public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
		Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
		this.urlPathHelper = urlPathHelper;
		this.corsConfigSource.setUrlPathHelper(urlPathHelper);
	}

	public UrlPathHelper getUrlPathHelper() {
		return urlPathHelper;
	}

	public void setPathMatcher(PathMatcher pathMatcher) {
		Assert.notNull(pathMatcher, "PathMatcher must not be null");
		this.pathMatcher = pathMatcher;
		this.corsConfigSource.setPathMatcher(pathMatcher);
	}

	public PathMatcher getPathMatcher() {
		return this.pathMatcher;
	}

	public void setInterceptors(Object[] interceptors) {
		this.interceptors.addAll(Arrays.asList(interceptors));
	}

	public void setCorsProcessor(CorsProcessor corsProcessor) {
		Assert.notNull(corsProcessor, "CorsProcessor must not be null");
		this.corsProcessor = corsProcessor;
	}

	/**
	 * Return the configured {@link CorsProcessor}.
	 */
	public CorsProcessor getCorsProcessor() {
		return this.corsProcessor;
	}

	public void setCorsConfigurations(Map<String, CorsConfiguration> corsConfigurations) {
		this.corsConfigSource.setCorsConfigurations(corsConfigurations);
	}

	/**
	 * Get the CORS configuration.
	 */
	public Map<String, CorsConfiguration> getCorsConfigurations() {
		return this.corsConfigSource.getCorsConfigurations();
	}

	//初始化时调用,初始化一些基本信息,这里主要是初始化一些拦截器
	@Override
	protected void initApplicationContext() throws BeansException {
		extendInterceptors(this.interceptors);//添加或修车intercept,现在并没有具体实现
		detectMappedInterceptors(this.adaptedInterceptors);//将springMVC容器或者父容器中的所有MappedInterceptor类型的Bean添加到mappedInterceptors属性中
		initInterceptors();
	}

	protected void extendInterceptors(List<Object> interceptors) {
	}

	//将springMVC容器或者父容器中的所有MappedInterceptor类型的Bean添加到mappedInterceptors属性中
	protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
		mappedInterceptors.addAll(
				BeanFactoryUtils.beansOfTypeIncludingAncestors(
						getApplicationContext(), MappedInterceptor.class, true, false).values());
	}

	//初始化Interceptor,将interceptors属性里所包含的对象按类型添加到mappedInterceptors或者adaptedInterceptors中。
	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));
			}
		}
	}

	protected HandlerInterceptor adaptInterceptor(Object interceptor) {
		if (interceptor instanceof HandlerInterceptor) {
			return (HandlerInterceptor) interceptor;
		}
		else if (interceptor instanceof WebRequestInterceptor) {
			return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
		}
		else {
			throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
		}
	}

	protected final HandlerInterceptor[] getAdaptedInterceptors() {
		int count = this.adaptedInterceptors.size();
		return (count > 0 ? this.adaptedInterceptors.toArray(new HandlerInterceptor[count]) : null);
	}

	protected final MappedInterceptor[] getMappedInterceptors() {
		List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				mappedInterceptors.add((MappedInterceptor) interceptor);
			}
		}
		int count = mappedInterceptors.size();
		return (count > 0 ? mappedInterceptors.toArray(new MappedInterceptor[count]) : null);
	}

	//获得一个HandlerExecutionChain
	@Override
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//从实现类中获得HanlderMethod
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);
		}
		//获得HandlerExecutionChain
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		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;
	}

	//模板方法,用于子类中实现,通过request去查找对应的执行方法HandlerMethod
	protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

	//
	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		//如果没有获得则创建一个
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
		//获得IP地址及端口后的URL地址
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		//在HandlerExecutionChain中添加拦截器
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				//根据lookupPath来获取Interceptor
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

	protected CorsConfiguration getCorsConfiguration(Object handler, HttpServletRequest request) {
		if (handler instanceof HandlerExecutionChain) {
			handler = ((HandlerExecutionChain) handler).getHandler();
		}
		if (handler instanceof CorsConfigurationSource) {
			return ((CorsConfigurationSource) handler).getCorsConfiguration(request);
		}
		return null;
	}
	protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
			HandlerExecutionChain chain, CorsConfiguration config) {
		if (CorsUtils.isPreFlightRequest(request)) {
			HandlerInterceptor[] interceptors = chain.getInterceptors();
			chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
		}
		else {
			chain.addInterceptor(new CorsInterceptor(config));
		}
		return chain;
	}

	private class PreFlightHandler implements HttpRequestHandler {
		private final CorsConfiguration config;
		public PreFlightHandler(CorsConfiguration config) {
			this.config = config;
		}
		@Override
		public void handleRequest(HttpServletRequest request, HttpServletResponse response)
				throws IOException {
			corsProcessor.processRequest(this.config, request, response);
		}
	}

	private class CorsInterceptor extends HandlerInterceptorAdapter {

		private final CorsConfiguration config;
		public CorsInterceptor(CorsConfiguration config) {
			this.config = config;
		}
		@Override
		public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
				Object handler) throws Exception {
			return corsProcessor.processRequest(this.config, request, response);
		}
	}

}

springMVC源码分析--AbstractHandlerMapping(二)的更多相关文章

  1. springmvc 源码分析(二)-- DiapartcherServlet核心调用流程分析

    测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git 项目结构代码如下: 一: cont ...

  2. springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)

    在之前的博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMethodMapping的父类AbstractHandlerMa ...

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

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

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

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

  5. springMVC源码分析--国际化实现Session和Cookie(二)

    上一篇博客springMVC源码分析--国际化LocaleResolver(一)中我们介绍了springMVC提供的国际化的解决方案,接下来我们根据springMVC提供的解决方案来简单的实现一个多语 ...

  6. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  7. springMVC源码分析--SimpleServletHandlerAdapter(二)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  8. springMVC源码分析--异常处理机制HandlerExceptionResolver执行原理(二)

    上一篇博客springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)中我们简单地实现了一个异常处理实例,接下来我们要介绍一下HandlerExceptio ...

  9. springMVC源码分析--HandlerInterceptor拦截器调用过程(二)

    在上一篇博客springMVC源码分析--HandlerInterceptor拦截器(一)中我们介绍了HandlerInterceptor拦截器相关的内容,了解到了HandlerInterceptor ...

随机推荐

  1. 一日一练-CSS CSS中percentage百分值的使用

    子曰:学好百分值,考试考百分 首先是确定CSS 中的percentage 都可以应用在CSS 中的哪些属性,以及这些属性的值如何进行计算的,参考CSS 参考手册进行统计. 定位(Positioning ...

  2. JS日期格式化转换方法

    1. 将日期转换为指定的格式:比如转换成 年月日时分秒 这种格式:yyyy-MM-dd hh:mm:ss 或者 yyyy-MM-dd.当然是网上的方法,只是总结下. Date.prototype.fo ...

  3. [HNOI 2008]GT考试

    Description 题库链接 问你长度为 \(n\) 的可含前导零的数字串中,不含长度为 \(m\) 的子串 \(X\) 有多少个,取模. \(1\leq n\leq 10^9,1\leq m\l ...

  4. codefroces 612E Square Root of Permutation

    A permutation of length n is an array containing each integer from 1 to n exactly once. For example, ...

  5. poj3728 商务旅行

    [Description]小 T 要经常进行商务旅行,他所在的国家有 N 个城镇,标号为 1,2,3,...,N,这 N 个城镇构成一棵树.每个城镇可以买入和卖出货物,同一城镇买入和卖出的价格一样,小 ...

  6. [ZJOI2007]报表统计

    题目描述 Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细观察,小Q发现统计一张报表实际上是维护一个非负整数数列,并 ...

  7. ●BZOJ 4289 PA2012 Tax

    ●赘述题目 算了,题目没有重复的必要. 注意理解:对答案造成贡献的是每个点,就是了. 举个栗子: 对于如下数据: 2 1 1 2 1 答案是 2: ●题解 方法:建图(难点)+最短路. 先来几个链接: ...

  8. ●BZOJ 1042 [HAOI2008]硬币购物

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1042 题解: 容斥原理,dp预处理首先跑个无限物品的背包dp求出dp[i]表示在四种物品都有 ...

  9. hdu 5115(2014北京—dp)

    题意: 有一排狼,每只狼有一个伤害A,还有一个伤害B.杀死一只狼的时候,会受到这只狼的伤害A和这只狼两边的狼的伤害B的和.如果某位置的狼被杀,那么杀它左边的狼时就会收到来自右边狼的B,因为这两只狼是相 ...

  10. Educational Codeforces Round 17F Tree nesting

    来自FallDream的博客,未经允许,请勿转载, 谢谢. 给你两棵树,一棵比较大(n<=1000),一棵比较小(m<=12) 问第一棵树中有多少个连通子树和第二棵同构. 答案取膜1e9+ ...