目录
2、getHandlerExecutionChain()方法
2.2、AbstractUrlHandlerMapping类
2.2.2.2、getHandlerInternal()方法
2.3、AbstractHandlerMethodMapping类
前言:
我们在之前的博文 SpringMVC原理分析之一MVC框架 中已经介绍了SpringMVC的处理一次请求的大致流程,为了节省篇幅在流程介绍中省去了核心九大组件的介绍。下面我们来看一看九大组件之一的处理器映射器的相关原理。本篇博文分析的spring版本为5.2.7.RELEASE。
-
HandlerMapping组件介绍
HandlerMapping接口定义主要用来提供request 请求对象和Handler 对象 映射关系的接口。所谓request对象比如我们web应用中的http 请求,Handler对象则指的是对应rquest请求的相关处理逻辑。该接口只有一个方法getHandler(),其实大部分情况下该方法并不是返回单纯的Handler处理器而是将该对象包装成包含Handler处理器和若干个与之匹配的interceptor 拦截器对象列表。
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
|
该请求对象入参是Http对应的请求对象,返回会值是HandlerExecutionChain对象,该对象包含一个处理器对象Handler和匹配该处理器的若干interceptors 拦截器列表 |
如上是HandlerMapping接口以及其目前所有子类的UML类图,从类图中可以看到HandlerMapping有一个初始的抽象类AbstractHandlerMapping,在该抽象类,分成两个体系一个是以AbstractUrlHandlerMapping(url和类级别的Handler处理器映射 url ->Controller)
一个是AbstractHandlerMethodMapping(url和method方法级别的Handler处理器,点到为止),下面就让我们通过源码来一起了解一下处理器映射器组件的相关功能。由于篇幅限制,此篇博文对于我们先对上述的两大分类的HandlerMaping进行分析。关于两大分类的博文扩展分析我们分别在后面的博客中进行介绍。
-
HandlerMapping体系结构介绍
2.1、AbstractHandlerMapping类
2.1.1、简要介绍
AbstractHandlerMapping是HandlerMapping的抽象实现,同时实现了Order接口继承了WebApplicationObjectSupport类,order接口主要是为了如果spring容器中有多个HandlerMapping,则按照order 排序去一次使用HandlerMapping获取handler对象,order小的优先被使用。由于该处理器抽象类继承WebApplicationObjectSupport对象,通过查看WebApplicationObjectSupport的继承关系,其也间接实现了ApplicationContextAware和ServlerContextAware,意味着该类在spring容器中被初始化完成后自动拥有ApplicationContext对象和ServletContext对象。
2.1.2、类的属性
分析一个类需要看该类的相关属性和方法(排除掉无意义的set/get方法)。下面就是罗列的AbstractHandlerMapping类的属性和方法
int order |
排序属性 默认最大值,如果不设置意味着其对应的处理器对象优先级最小 |
Object defaultHandler |
对于通过该处理器映射器如果没有获取到对应的Handlerm,则使用的默认Handler, 可以通过xml/注解的形式配置。 |
UrlPathHelper urlPathHelper |
Url路径匹配的帮助类,包含ur编码方式设置获取,或者根据请求请求路径等方法 |
PathMatcher pathMatcher |
Spring提供的路径匹配策略接口的路径匹配器 |
final List<Object> interceptors |
我们可以通过该属性来设置相关的拦截器,设置的方式可以通过xml配置,也可以通过子类的钩子extendInterceptors扩展设置 |
final List<HandlerInterceptor> adaptedInterceptors |
该集合下的拦截器不需要匹配会通过getHandler()方法全部添加到HandlerExecutionChain中 |
final List<MappedInterceptor> mappedInterceptors |
该集合下的拦截器需要与请求url进行匹配,匹配成功才可以添加到HandlerExecutionChain |
前面的属性主要说一下三种拦截器集合
- Interceptors
用于配置SpringMVC的拦截器,这里有两种设置方式一种是注册HandlerMapping的时候通过属性设置。另一种是通过子类extendInterceptors()方法来进行设置
- mappedInterceptors
该集合中的元素不是我们常见的HandlerInterceptor,而是MappedInterceptor,该类中包含PathMatcher的路径匹配对象,表明该拦截器需要和url进行匹配只有匹配成功的拦截器才会被包装到HandlerExecutionChain对象中。
- adaptedInterceptors
该集合下的拦截器不需要匹配,会通过getHandler()方法全部包装到HandlerExectutionChain对象中。
2.1.2、类的方法
-
initApplicationContext()方法
上面我们提到AbstractHandlerMapping继承了WebApplicationObjectSupport对象,提供了一个initApplicationContext()方法,这个方法主要是对上面的三种类型的拦截器集合进行相关处理。
@Override
protected void initApplicationContext() throws BeansException {
//spring提供钩子函数,子类可以实现该方法来为集合设置拦截器
extendInterceptors(this.interceptors);
//从spring容器中获取所有MappedInterceptor
detectMappedInterceptors(this.mappedInterceptors);
//将所有设置在interceptors中的拦截器按照类型分别添加到
//mappedInterceptors和adaptedInterceptors中
initInterceptors();
}
1、getHandler()方法
AbstractHandlerMapping的核心方法就是该方法,主要作用是根据请求获取包装了Handler对象和拦截器的HandlerExecutionChain对象。该方法采用模板方法获取拦截器处理器链。
/**
* 根据请求对象获取对应的HandlerExecutionChain 对象
* @param request 请求对象
* @return 返回处理器执行链
* @throws Exception
*/
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//交由子类实现的根据请求获取处理器的具体逻辑 不同的子类获取Handler的逻辑不同
//这个也是众多子类的扩展点
Object handler = getHandlerInternal(request);
//如果没有获取到Handler 则获取默认的Handler
//默认的处理器可以通过配置映射器实例的时候通过属性设置
if (handler == null) {
handler = getDefaultHandler();
}
//如果默认的Handler还是没有则返回空
if (handler == null) {
return null;
}
//Handler处理器是字符串类型