[spring boot源码解析] HandlerMapping从何而来

1、为什么写这篇文章        

        最近在写脚手架,为了解决统一异常处理的问题,又看了一次spring mvc的 DispatcherServlet 的处理流程。让我觉得好奇和感兴趣的是,在debug的过程中,spring boot在默认情况下,为我们准备了7个HandlerMapping,而且与XML配置注解驱动下的spring mvc提供的默认HandlerMapping有很大不同。

        本文的目的是 解读这些默认的handlerMapping,分别在xml注解驱动和spring boot 下是怎么得来的。        

2、一起回忆XML配置中的注解驱动   

     熟悉spring容器的初始化流程的同学们可能知道,spring 容器在解析XML配置文件的阶段会处理自定义的名字空间,例如 mvc: ,mvc这个名字空间就是在该阶段处理。

      在该阶段,spring读取每个包 META-INF 下的 spring.schemas 和 spring.handlers 文件,这些文件映射了名字空间和处理该名字空间的处理器。spring实例化这些处理器,并找到处理对应名字空间的处理器,运行init方法。

    现在回到本文的配角:mvc。 该名字空间的处理器是 MvcNamespaceHandler MvcNamespaceHandler 的 init方法中,向spring 容器中注册了各种各样的 BeanDefinitionParser实例,这些实例将解析各自的mvc名字空间下的元素。其中,注解驱动 <mvc:annotation-driven> 节点的annotation-driven 元素由 AnnotationDrivenBeanDefinitionParser 解析器解析 。

    AnnotationDrivenBeanDefinitionParser 解析器在解析 annotation-driven 元素时被调用。在解析阶段,会向spring容器中注册一些默认的bean。例如大家熟悉的HandlerMapping 、HandlerAdapter等。在这里,将会向spring 容器注册这些bean的beanDefinition,容器在接下来的流程中会实例化bean并注册到容器中。下面是默认的3个handlerMapping。

c69446839ef14c77d7e75cfeca1ebb00202.jpg

 3、spring boot下的handlerMapping

    这道前菜真是太久了,下面开始本文标题相关的内容。

    spring boot为了减少开发者的配置工作量,提供了各种各样的自动配置类,官方的自动配置类都在spring-boot-autoconfigure 包下。

      spring boot是在什么时候、怎么做到自动配置的呢?

      我们注意到 EnableAutoConfiguration 注解上有个@Import注解,该注解相当于XML配置中的 <import> 引入其它配置文件。@Import注解中指定了 选择器 AutoConfigurationImportSelector ,该选择器的作用是在 selectImports() 方法中从spring.factories 文件中获取 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration  指定的所有类。然后把这些类都加入到了容器中。另外,这些类有个共同特点:它们都有个 @Configuration 注解。Spring中对Configuration类的解析是通过 ConfigurationClassPostProcessor 进行的。具体的过程大家可以自行查看代码。总之,@Configuration 注解标识的类中所有的@Bean的类又这样实例化并放到了容器中。

        我们花了一些篇幅介绍 EnableAutoConfiguration  的原理,那么有什么用呢?

        回到 spring.factories 文件中,我们在 org.springframework.boot.autoconfigure.EnableAutoConfiguration 中发现了关键类:WebMvcAutoConfiguration

        说到这里,我们看下spring boot启动下,默认情况下,DispatcherServlet中的HandlerMapping有哪些。通过debug,可以看到spring boot默认给我们准备了7个HandlerMapping

31fbaaa2efb3c6a59d91b015f21debe6a51.jpg

   下面简单说明下前5个HandlerMapping的作用和匹配的URL。

(1)第一个SimpleUrlHandlerMapping

    该bean在 WebMvcAutoConfiguration 的内部配置类 FaviconConfiguration 中声明。它匹配的URL路径是**/favicon.ico,作用是响应浏览器获取收藏夹中的icon文件。

(2)RequestMappingHandlerMapping

    该bean在 WebMvcAutoConfiguration 的内部配置类 EnableWebMvcConfiguration 中声明。它和XML的注解驱动一样,匹配在Controller中@RequestMapping注解指定的URL。

(3)WelcomePageHandlerMapping

  该bean在 WebMvcAutoConfiguration 的内部配置类 WebMvcAutoConfigurationAdapter 中声明。给URL路径是/或者/index映射到欢迎页面。

(4)BeanNameUrlHandlerMapping

   bean的名称(也就是beanID)作为URL,由匹配该URL的Controller处理业务。Controller必须继承AbstractController。这这这这。。。又想起了structs。基本不会在工作中使用这个玩意。

(5)第二个SimpleUrlHandlerMapping

    该bean在WebMvcAutoConfiguration 的内部配置类 EnableWebMvcConfiguration 的父类 WebMvcConfigurationSupport 中声明。

@Bean
public HandlerMapping resourceHandlerMapping() {}

    从该bean的名称,可以知道它是专门用于映射资源文件的handlerMapping。看下它的URL与handler的映射关系

2be280ade575f4d3926671534174e668d4f.jpg

可以看到,我们的资源文件将由ResourceHttpRequestHandler处理、获取并返回。

4、小结    

    从上面可以看到,在默认情况下,spring boot给我们准备了7个HandlerMapping,每个HandlerMapping都有其明确清晰的职责。我们还需要认识到一个问题,不管我们请求任何的URL,都会被这7个HandlerMapping映射到对应的Handler上处理,即使最坏的404,会被SimpleUrlHandlerMapping 映射到ResourceHttpRequestHandler中处理。

     到这里,已经为接下来分析spring boot对异常的处理过程做了铺垫,后面将会另写文章分析404/500/异常的处理过程。

转载于:https://my.oschina.net/thinwonton/blog/1839909

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值