猫耳山在天边 2019-06-27
通过前三章的分析,我们简要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个HandlerMapping相同的部分。本节补充下这块内容。
本系列文章是基于Spring5.0.5RELEASE。
类的继承关系,如下图:
我们知道Spring MVC将请求发送到Handler(Controller)处理器的功能是通过HandlerMapping组件完成的,HandlerMapping组件除了能找到Handler,还对拦截器进行了处理,具体实现是通过AbstractHandlerMapping抽象类完成的。
HandlerMapping接口只定义了一个方法getHandler,其作用是返回请求的处理链HandlerExecutionChain,该对象封装了请求的拦截器以及请求处理Handler,方法定义如下:
@Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
类声明源码如下:
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { // ... ... }
从类的定义可知道,AbstractHandlerMapping抽象类继承WebApplicationObjectSupport并实现了HandlerMapping和Ordered接口,其中:
简言之,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,共同学习、共同进步,谢谢!