简介
目录
AbstractDetectingUrlHandlerMapping
AbstractControllerUrlHandlerMapping
映射器的作用就是解析出来url和handler的关系,并且保存这样的关系,在每次请求到来时,查找这个handler。handler并未有明确的要求,但是从spring原本实现上看,handler主要有对象级别和方法级别两种.
{@link HandlerMapping}为高级接口定义,所有的HandlerMapping都是基于它实现的。但是它仅仅只是定义了,如何通过Request查找对应的HandlerExecutionChain对象,并未定义如何注册url和handler的关系,它的默认实现是 AbstractHandlerMapping,而它只提供了org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandlerInternal方法,用于查找url与handler的关系。并且将找到的handler封装成HandlerExecutionChain对象,这个对象作用后面再讲。
{@link AbstractHandlerMapping}有两个实现类,分别是从对象级别以及方法级别上查找url和handler的映射关系,这两个实现类分别是:
- AbstractUrlHandlerMapping:从对象级别定义url和handler的映射关系,它的内部是通过一个map来维护这个关系的,但是它只定义了url和handler的查找关系,以及提供了注册url与handler关系的接口,并未实现查找url与handler的映射关系的功能(这个功能是由子类实现的)
-
AbstractHandlerMethodMapping:从方法级别定义url和handler的映射关系,它的内部是通过一个注册中心来维护这个关系的,即{@link AbstractHandlerMethodMapping.MappingRegistry},并且它支持的是{@link org.springframework.web.bind.annotation.RequestMapping}的注解。
基于对象级别映射关系的HandlerMapping
AbstractUrlHandlerMapping
它处理的handler是一个bean,但这个bean又分为实现了特定接口的bean和不指定特定实现的bean。注意该bean提供了查找关系的模式,也提供了注册url和handler关系的方法,但是就是没有实现查找url与handler关系的方法,所以它的子类必须得实现这个关系。
springmvc提供了如下两种实现:
-
自己指定url和handler关系映射的,即通过prop指定,其为{@link SimpleUrlHandlerMapping}
-
通过bean工厂的所有的bean,并根据bean本身去解析bean的url和handler关系的,即{@link AbstractDetectingUrlHandlerMapping}
AbstractDetectingUrlHandlerMapping
它实现了initApplicationContext的方法,该方法可以获取ApplicationContext,接着会从ApplicationContext获取所有的bean,并且进行解析。
对于通过bean本身去解析bean的url和handler关系的类,该类有分为两种:
- 第一种是通过bean的名称去解析,而bean的名称就是我们定义bean的时候制定的。即
{@link BeanNameUrlHandlerMapping}
- 第二种则是通过实现了特定接口或者注解的bean去解析的bean,即
{@link AbstractControllerUrlHandlerMapping}
AbstractControllerUrlHandlerMapping
该类通过,查找固定实现了{@link Controller}接口或者 {@link org.springframework.stereotype.Controller} 的bean来实现bena的关系映射,他又进一步分为三种查找关系
-
bean的name是一个url结构的。对应的实现类为{@link ControllerBeanNameHandlerMapping},它与BeanNameUrlHandlerMapping的区别是,他必须实现实现了{@link Controller}接口或者 {@link org.springframework.stereotype.Controller},并且他还支持前缀、后缀适配、过滤适配等。
-
bean的包路径形成url结构的,对应的实现类为{@link ControllerClassNameHandlerMapping},它的作用,就是讲bean所在的包当做url的一部分,进行url匹配。
-
bean上注解了{@link org.springframework.web.bind.annotation.RequestMapping}的,目前该方法即将淘汰,使用AbstractHandlerMethodMapping的进行替换和支持。这个方法与AbstractHandlerMethodMapping的区别之处在于,他解析结果是对象级别的,比如你一个bean中注解了多个requestmapping,它的内部存的是一个requestmapping的url与这个bean的映射关系,而AbstractHandlerMethodMapping则是存了一个requestmapping与这个方法级别的映射关系
基于方法级别的HandlerMapping
AbstractHandlerMethodMapping
这个方法是处理方法级别的映射,这个方法实现的原理就是遍历ApplicationContext的所有的bean,在afterPropertiesSet中实现,然后找到这个bean的所有方法进行处理。
这个类还是 一个泛型类,这个泛型的作用就是如何包装method的信息。如我们所熟悉的@RequestMapping注解的方法,解析得到的就是一个RequestMappingInfo对象。
但无论是什么,最终都会转变成org.springframework.web.method.HandlerMethod对象,而org.springframework.web.method.HandlerMethod就可以理解成我们所谓的handler。
重要说明
从上面来看,通过handlermapping,我们得到的handler有两种,一种方法级别的handler,一种是对象级别的handler。
但是spring并不会直接使用这个handler,而是使用HandlerExecutionChain进行了封装。HandlerExecutionChain封装了什么呢?
1.对handler的调用的拦截,即HandlerInterceptor。HandlerInterceptor就是一个接口,用于拦截handler的调用前后回调。
2.解决跨域问题。跨域问题另行了解