HandlerMapping

HandlerMapping在这个SpringMVC体系结构中有着举足轻重的地位,充当着url和Controller之间映射关系配置的角色。主要有三部分组成:HandlerMapping映射注册、根据url获取对应的处理器、拦截器注册。

看下HandlerMapping的继承结构:
这里写图片描述
由图中可以看出HandlerMapping家族分两支,一支继承AbstractUrlHandlerMapping,另一支继承AbstractHandlerMethodMapping,而这两支都继承自AbstractHandlerMapping。

AbstractHandlerMapping

初始化

AbstractHandlerMapping是HandlerMapping的抽象实现,所有的HandlerMapping都继承自AbstractHandlerMapping。AbstractHandlerMapping采用模板形式设计了HandlerMapping实现的整体结构,子类只需要通过模板方法提供一些初始值和算法。
PS:在SpringMVC中模板形式是最常见的,首先使用一个抽象类在顶层设计好功能结构,子类继承去实现。这种方法在很多框架中都很重要。
这里写图片描述
AbstractHandlerMapping继承自WebApplicationObjectSupport,所以其初始化方法为initApplicationContext()。
这里写图片描述
这里写图片描述
Interceptor为拦截器
extendInterceptors()是一个模板方法,用于子类增加Interceptor,不过SpringMVC中并没有使用。
这里写图片描述
detectMappedInterceptors()用于将SpringMVC容器及其父容器中所有类型为MappedInterceptor类型的拦截器添加到HandlerMapping的mappedInterceptors属性之中。
这里写图片描述
initInterceptors()的作用是初始化Interceptor,具体的内容是按照interceptors属性中的Interceptor按照类型分类到mappedInterceptors和adaptedInterceptors之中。

getHandler

HandlerMapping是通过getHandler来获取Handler和Interceptor的
这里写图片描述
这里写图片描述
getHandler的步骤:(1)从模板方法getHandlerInternal中找, 如果找不到,(2)使用defaultHandler,defaultHandler是配置HandlerMapping的时候设置的,如果找到的Handler是String类型,那么去Spring容器中找同名的Bean作为handler。(3)执行getHandlerExecutionChain(handler, request)
这里写图片描述
首先创建HandlerExecutionChain变量,之后将所有的AdaptedInterceptors和符合要求的mappedInterceptor加入到HnadlerExecutionChain之中并返回。

AbstractUrlHandlerMapping

AbstractUrlHanderMapping是通过url来匹配Handler的,主要的方式就是将url和handler存入到一个本地的handlerMap属性之中,另外还单独定义了处理”/”请求的rootHandler
这里写图片描述
AbstractHandlerMapping之中设计了子类获取handler的接口为getInternalHandler
这里写图片描述
需要看下lookupHandler和buildPathExposingHandler
这里写图片描述
这里写图片描述
buildPathExposingHandler方法用于给查找到的Handler注册两个拦截器PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor,这两个是内部拦截器,主要作用就是将当前url实际匹配的pattern,匹配条件以及url模板参数等设置到request的属性之中,这样后面的处理过程就可以直接从request的属性中获取。而不需要再查找一遍了。
这里写图片描述
这里写图片描述

handlerMap的初始化

handlerMap的初始化通过registerHandler方法进行,这个方法承担AbstractUrlHandlerMapping的创建工作(handler初始化),不过并不是自己调用,而是给子类调用。
这里写图片描述
这里写图片描述
注册很简单,看map里面原来有没有传入url,如果没有就put进去,有就检测一下是不是同一个handler,如果不同就是Exception了,总不能相同的url对应两个不同的hadler吧。同事要注意一下,rootHandler(”/”)和defaultHandler(“/*”)的使用。

SimpleUrlHandlerMapping

SimpleUrlHandlerMapping自己定义了一个Map变量,这样做的有两个作用,第一是方便配置,第二是可以在注册前做一些预处理,比如确保url的格式。将所有的url和handler对应关系放入这个Map后再注册到父类的Map之中。SimpleUrlHandlerMapping创建的时候通过重写父类的initApplicationContext方法调用了registerHandlers方法完成Handler的注册。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
最后调用的registerHandler就是父类AbstractUrlHandlerMapping中的方法。

AbstractDetectingUrlHandlerMapping

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
获取容器中的bean如果能解析到url那么调用父类的registerHandler方法注册。
如何解析到url使用方法determineUrlsForHandler()是一个模板方法,子类具体实现。
这里写图片描述
从继承结构中看AbstractDetectingUrlHandlerMapping有两个子类BeanNameUrlHandlerMapping,AbstractControllerUrlHandlerMapping

BeanNameUrlHandlerMapping

这里写图片描述
BeanNameUrlHandlerMapping只有一个方法,重写了determineUrlsForHandler(String beanName),判定规则为beanName的开头是不是”/”,并且搜寻了bean的所有alias。

AbstractControllerUrlHandlerMapping

AbstractControllerUrlHandlerMapping是将实现了Controller接口或者注释了@Controller的bean作为Handler,并且通过设置了excludePackages和excludedClasses将不包含的bean和不包含的包下面的所有bean排除在外。主要是将handler找出来,具体使用什么url在模板方法buildUrlsForHandler中由子类实现
这里写图片描述
这里写图片描述
这里写图片描述
注意使用什么url有模板方法buildUrlsForHandler确定
这里写图片描述
这里写图片描述
isControllerType(beanClass)判定该bean是不是controller
这里写图片描述
这里写图片描述

看下AbstractControllerUrlHandlerMapping的两个子类:
这里写图片描述
这里写图片描述

AbstractHandlerMethodMapping系列

AbstractHandlerMethodMapping系列是将Method作为Handler来使用的,这也是我们现在用的最多的一种Handler,比如@RequstMapping注释的Method就是这种Handler。
这里写图片描述
这里写图片描述
弄清楚AbstractHandlerMethodMapping最为关键的是弄清楚其定义的三个Map的含义
模板参数T表示一种匹配Handler的条件的类
看一下子类中的使用
这里写图片描述
这里写图片描述
RequestMappingInfo实现了RequestCondition接口,此接口专门保存从request提取出来的用于匹配Handler的条件
这里写图片描述
这里写图片描述
AbstarcatRequestCondition重写了equals(),hashCode(),toString()三个方法,其有8个子类,除了CompositeCondition,每个子类表示一种匹配条件。比如PatternRequestCondition使用url做匹配,RequestMethodRequestCondition使用RequestMethod做匹配等。CompositeRequestCondition本身并不实际做匹配,而是可以将多个别的RequestCondition封装到自己的一个变量里,在用的时候遍历封装RequestCondition的那个变量里所有的RequestCondition进行匹配,这个就是责任链模式。这种模式在SpringMVC之中非常常见,一般就是命名为CompositeXXX或者XXXComposite,主要的左右就是为了方便调用。
这里写图片描述
这里写图片描述

RequstCondition的另一个实现就是这里要说的RequestMappingInfo,它其实是用七个变量保存了七个RequstCondition,在匹配时使用那七个变量进行匹配,这也就是可以在@RequestMapping中给处理器指定多种匹配方式的原因。

具体的代码分析就略过了。

现在说下AbstractHandlerMethodMapping的三个Map

handlerMethods:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值