博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC之源码分析--HandlerMapping(五)
阅读量:6835 次
发布时间:2019-06-26

本文共 5188 字,大约阅读时间需要 17 分钟。

概述

通过前三章的分析,我们简要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个HandlerMapping相同的部分。本节补充下这块内容。

本系列文章是基于Spring5.0.5RELEASE。

类图

类的继承关系,如下图:

我们知道Spring MVC将请求发送到Handler(Controller)处理器的功能是通过HandlerMapping组件完成的,HandlerMapping组件除了能找到Handler,还对拦截器进行了处理,具体实现是通过AbstractHandlerMapping抽象类完成的。

源码分析

  • HandlerMapping

HandlerMapping接口只定义了一个方法getHandler,其作用是返回请求的处理链HandlerExecutionChain,该对象封装了请求的拦截器以及请求处理Handler,方法定义如下:

@NullableHandlerExecutionChain 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对象中。

该类的入口方法,源代码如下:

/** * 初始化拦截器 */@Overrideprotected void initApplicationContext() throws BeansException {    // 提供给子类去重写的,不过Spring并未去实现    extendInterceptors(this.interceptors);    // 加载拦截器    detectMappedInterceptors(this.adaptedInterceptors);    // 归并拦截器    initInterceptors();}/** * 空实现 */protected void extendInterceptors(List interceptors) {}/** * 从上下文中加载MappedInterceptor类型的拦截器,比如我们在配置文件中使用 * 
* 标签配置的拦截器 */protected void detectMappedInterceptors(List
mappedInterceptors) { mappedInterceptors.addAll( BeanFactoryUtils.beansOfTypeIncludingAncestors( obtainApplicationContext(), MappedInterceptor.class, true, false).values());}/** * 合并拦截器,即将
中的拦截器与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@Nullablepublic 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;}/** * 钩子函数,需子类实现 */@Nullableprotected 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://rcxkl.baihongyu.com/

你可能感兴趣的文章
SpringMvc+Hibernate+Mysql保存表情字符(昵称)到数据库报错的问题?
查看>>
微软2016校园招聘在线笔试 B Professor Q's Software [ 拓扑图dp ]
查看>>
Linux 典型应用之Mysql
查看>>
c语言操作符的优先级
查看>>
Python-JS事件与面向对象操作
查看>>
【高德地图API】那些年我们一起开发的APP—即LBS应用模式分享
查看>>
IDDD 实现领域驱动设计-理解领域和子域
查看>>
Linux内核源代码目录树结构
查看>>
Python标准库之urllib,urllib2自定义Opener
查看>>
jquery 自动完成 Autocomplete插件汇总
查看>>
jquery表单选择器
查看>>
日志插件 log4net 的使用
查看>>
小程序一:小程序的框架
查看>>
使用delphi 开发多层应用(八)客户端更新数据到kbmMW服务器
查看>>
HDU_3062 Party (2-SAT)
查看>>
dynamic_shift_reg SRL16E
查看>>
尝试用微博记录 SQL Server 2012开发者训练营笔记
查看>>
.Net中的5种事务总结
查看>>
为什么 Git 比 SVN 好
查看>>
关于Qt的MVC模型思想(转载)
查看>>