概述
通过前三章的分析,我们简要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个HandlerMapping相同的部分。本节补充下这块内容。
本系列文章是基于Spring5.0.5RELEASE。
类图
类的继承关系,如下图:
我们知道Spring MVC将请求发送到Handler(Controller)处理器的功能是通过HandlerMapping组件完成的,HandlerMapping组件除了能找到Handler,还对拦截器进行了处理,具体实现是通过AbstractHandlerMapping抽象类完成的。
源码分析
- HandlerMapping
HandlerMapping接口只定义了一个方法getHandler,其作用是返回请求的处理链HandlerExecutionChain,该对象封装了请求的拦截器以及请求处理Handler,方法定义如下:
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
- AbstractHandlerMapping
类声明源码如下:
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {
// ... ...
}
从类的定义可知道,AbstractHandlerMapping抽象类继承WebApplicationObjectSupport并实现了HandlerMapping和Ordered接口,其中:
- 继承WebApplicationObjectSupport类提供了上下文ApplicationContext和ServletContext
- 实现HandlerMapping接口为我们提供查找handler处理器功能
- 实现Ordered接口,以提供排序能力,比如系统中使用多个HandlerMapping,可以定义每个HandlerMapping的顺序
简言之,AbstractHandlerMapping类为我们提供上下文环境、初始化拦截器并封装到HandlerExecutionChain对象中。
该类的入口方法,源代码如下:
/**
* 初始化拦截器
*/
@Override
protected void initApplicationContext() throws BeansException {
// 提供给子类去重写的,不过Spring并未去实现
extendInterceptors(this.interceptors);
// 加载拦截器
detectMappedInterceptors(this.adaptedInterceptors);
// 归并拦截器
initInterceptors();
}
/**
* 空实现
*/
protected void extendInterceptors(List<Object> interceptors) {
}
/**
* 从上下文中加载MappedInterceptor类型的拦截器,比如我们在配置文件中使用
* <mvc:interceptors></mvc:interceptors>
* 标签配置的拦截器
*/
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
/**
* 合并拦截器,即将<mvc:interceptors></mvc:interceptors>中的拦截器与HandlerMapping中通过属性interceptors设置的拦截器进行合并
*/
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");
}
// 适配后加入adaptedInterceptors
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
/**
* 适配HandlerInterceptor和WebRequestInterceptor
*/
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());
}
}
至此,拦截器初始化完成,接下来我们分析getHandler方法,源码如下:
/**
* 返回请求处理的HandlerExecutionChain
*/
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// getHandlerInternal()为抽象方法,具体需子类实现
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 = obtainApplicationContext().getBean(handlerName);
}
// 将请求处理器封装为HandlerExectionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
// 对跨域的处理
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
/**
* 钩子函数,需子类实现
*/
@Nullable
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
/**
* 构建handler处理器的HandlerExecutionChain,包括拦截器
*/
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
// 迭代添加拦截器
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
// 如果拦截器是MappedInterceptor,判断是否对该handler进行拦截,是的情况下添加
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else { // HandlerInterceptor直接添加,即通过HandingMapping属性配置的拦截器
chain.addInterceptor(interceptor);
}
}
return chain;
}
总结
本节我们补充了拦截器的加载初始化过程以及getHandler方法的实现分析,希望对大家有所帮助。
最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。