DispatcherServlet
中持有一个 List<HandlerMapping> 的组件,那么HandlerMapping
究竟是什么东西呢?
我们通过debug的方式看看 handlerMappings 里面具体有什么?
可以看到这 handlerMappings 这个list里面一共有5个元素,这5个中有3个是WebMvcConfigurationSupportXXX
类型的代理对象,另外2个是RequestMappingHandlerMapping
和BeanNameUrlHandlerMapping
。
我们看看官方文档上又是怎么说的,在https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet 这个页面里有对HandlerMapping
的说明。
从官方描述看,HandlerMapping
是将请求与处理该请求的控制器(controller)、拦截器(intercepter)做了一个映射关系。对于一个请求,通过特定的HandlerMapping
,就能找到需要用哪个controller的哪个方法来处理请求,并且处理这个请求需要执行哪些拦截器。这个寻找功能就是HandlerMapping
接口中声明的HandlerExecutionChain getHandler(HttpServletRequest request)
方法,该方法返回了一个叫 HandlerExecutionChain
(处理器执行链)的实例,其中包装了控制器、拦截器列表这些数据。
1 | public interface HandlerMapping { |
通过debug的方式查看HandlerExecutionChain
对象中封装的信息。
查看HandlerExecutionChain
的源码可以看到它持有一个Object
类型成员变量 handler ,它可能是一个HandlerMethod
(封装了xxxController及请求对应的方法等)对象,也有可能是一个Controller
对象、HttpRequestHandler
对象或Servlet
对象,而这个 handler 具体是什么对象,是与所使用的 HandlerMapping 实现类有关。
前面也说到 DispatcherServlet 中的 handlerMappings 中有好几个不同的HandlerMapping
实例,并且对于一个请求,会由其中的一个实例来获取到HandlerExecutionChain
对象。
1 | /** |
那么,一个具体请求到底会通过哪个HandlerMapping
实例来获取HandlerExecutionChain
对象呢?这就又要回到官方文档里描述的,HandlerMapping
接口的两个主要实现类是RequestMappingHandlerMapping
和SimpleUrlHandlerMapping
,它们两个分别用来处理SpringMVC中不同形式的url映射方式。
我们知道可以通过注解@Controller
或@RestController
注解方式来声明一个 Controller,然后使用@RequestMapping
来修饰类或方法,这种方式其实是由RequestMappingHandlerMapping
映射处理器来对请求进行映射的。也可以概括地说,RequestMappingHandlerMapping
是专门支持@RequestMapping
注解声明方式的请求映射处理器。
那么SimpleUrlHandlerMapping
又用于处理哪种情况呢,那就是采用实现Controller
接口或实现HttpRequestHandler
接口的类,这种声明Controller的方式是早期的做法,现在在实际开发中用的很少了但是也是SpringMVC所支持的。
如下我们分别新建两个类分别实现Controller
接口和实现HttpRequestHandler
接口做具体的演示:
实现Controller接口的方式:
实现HttpRequestHandler接口的方式:
除了我们自己的实现,SpringMVC框架本身也有类实现了Controller
接口等,比如:UrlFilenameViewController
类、ServletForwardingController
类等,但这些类的实例是需要我们通过配置去注入到IOC容器中。
有了上面的实现类,再进行debug,就可以验证前面对于RequestMappingHandlerMapping
和SimpleUrlHandlerMapping
的论述了,至此我们应该也就大概了解SpringMVC中的 HandlerMapping 是什么了。