在springmvc中,如何根据url找到controller以及对应方法,依赖的是HandlerMapping接口的getHandler方法

在spring容器中默认注册的HandlerMapping有以下五种:

  • RequestMappingHandlerMapping
  • BeanNameUrlHandlerMapping
  • SimpleUrlHandlerMapping
  • RouterFunctionMapping
  • WelcomePageHandlerMapping

本文主要探索spring和springboot启动过程中RequestMappingHandlerMapping的注入

Spring中RequestMappingHandlerMapping的注入

环境

springmvc版本:5.1.9.RELEASE

过程

  1. 在springmvc中,使用注解需要在xml了加入注解声明

    <!-- 注解扫描 -->
    <context:component-scan base-package="com.xiaofan"/>
    <!--使用mvc注解声明 -->
    <mvc:annotation-driven/>
  2. 启动web服务器,我用的是tomcat8

  3. spring启动,注册BeanDefinition,

    spring会扫描xml文件,将配置文件中的bean信息注册成BeanDefinition,当发现springmvc的xml配置文件中有annotation-driven标签时,会调用AnnotationDrivenBeanDefinitionParser来解析该标签

    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext context) {
    ...
    // 前面省略代码
    RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
    handlerMappingDef.setSource(source);
    handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerMappingDef.getPropertyValues().add("order", 0);
    handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); if (element.hasAttribute("enable-matrix-variables")) {
    Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
    handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
    } configurePathMatchingProperties(handlerMappingDef, element, context);
    // String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName()
    readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
    // 后面省略代码
    ...
    return null;
    }
  4. spring将BeanDefinition通过反射实例化成bean注入到容器中

那么问题来了,如果没有mvc:annotation-driven标签,RequestMappingHandlerMapping还会被注入到spring容器中吗?

答:会的,前提是xml中没有配置任何一个HandlerMapping。

过程如下:

  1. 在启动过程中,会调用DispatcherServlet的init()方法(我也不知道是在哪个步骤调用的,希望知道的大佬告知,不胜感激)

  2. DispatcherServlet#onRefresh → DispatcherServlet#initStrategies → DispatcherServlet#initHandlerMappings

    private void initHandlerMappings(ApplicationContext context) {
    ...
    // 前面省略代码
    // 当没有配置任何handlerMapping时,则使用默认的handlerMapping
    if (this.handlerMappings == null) {
    // 从DispatcherServlet.properties拿org.springframework.web.servlet.HandlerMapping
    // 所以默认的有BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
    // 最终还是调用BeanFactory#createBean()生成实例
    this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
    if (logger.isTraceEnabled()) {
    logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
    "': using default strategies from DispatcherServlet.properties");
    }
    }
    }

SpringBoot中RequestMappingHandlerMapping的注入

在springboot中的注入,依赖的是springboot的自动装配

环境

Springboot版本:2.4.3

过程

  1. spring-boot-autoconfigure包下的spring.factories中有WebMvcAutoConfiguration

  2. WebMvcAutoConfiguration的内部类EnableWebMvcConfiguration#requestMappingHandlerMapping()

    @Bean
    @Primary
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping(
    @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
    @Qualifier("mvcConversionService") FormattingConversionService conversionService,
    @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    // Must be @Primary for MvcUriComponentsBuilder to work
    return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,
    resourceUrlProvider);
    }

问题

在spring环境中,DispatcherServlet的init方法在web服务器启动过程中就被调用了,而在springboot环境中,只有在DispatcherServlet被第一次调用的时候,才会执行init方法,有同学知道原因吗?不胜感激

springmvc源码笔记-HandlerMapping注入的更多相关文章

  1. springmvc源码笔记-RequestMappingHandlerMapping

    下图是springmvc的执行流程 图片来源:https://www.jianshu.com/p/8a20c547e245 DispatcherServlet根据url定位到Controller和方法 ...

  2. SpringMVC源码解读 - HandlerMapping

    SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大 ...

  3. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

  4. springMVC源码笔记

    springMVC 设计总览 下图来源:https://www.cnblogs.com/fangjian0423/p/springMVC-directory-summary.html 下图来源:htt ...

  5. SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping请求分发

    AbstractHandlerMethodMapping实现接口getHandlerInternal,定义查找流程 RequestMappingInfoHandlerMapping根据RequestM ...

  6. SpringMVC源码解读 - HandlerMapping - AbstractUrlHandlerMapping系列request分发

    AbstractHandlerMapping实现HandlerMapping接口定的getHandler 1. 提供getHandlerInternal模板方法给子类实现 2. 如果没有获取Handl ...

  7. SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化

    摘要: SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定. 初始化时,通过setMappings(Prop ...

  8. springmvc源码笔记-HandlerMethodReturnValueHandler

    返回值解析器 用于对controller的返回值进行二次处理 结构 // 返回值解析器 public interface HandlerMethodReturnValueHandler { // 判断 ...

  9. SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping初始化

    RequestMappingHandlerMapping ,用于注解@Controller,@RequestMapping来定义controller. @Controller @RequestMapp ...

随机推荐

  1. 这 BUG,绝了

    上周只上了三天班,但我也丝毫不敢懈怠,BUG 更是一个也没少写. 看着满屏幕的 ERROR,我陷入沉思.为什么我写的代如此烂,无法像大牛们写的那般优雅? 越想越自卑,越想越抑郁.我觉得这样不行,一定得 ...

  2. 445. Add Two Numbers II - LeetCode

    Question 445. Add Two Numbers II Solution 题目大意:两个列表相加 思路:构造两个栈,两个列表的数依次入栈,再出栈的时候计算其和作为返回链表的一个节点 Java ...

  3. MySQL启动与多实例安装

    启动方式及故障排查 一.几个问题 1.1 /etc/init.d/mysql 从哪来 cp /usr/local/mysql/support-files/mysql.server /etc/init. ...

  4. CSAPP 之 ShellLab 详解

    前言 本篇博客将会详细介绍 CSAPP 之 ShellLab 的完成过程,实现一个简易(lou)的 shell.tsh 拥有以下功能: 可以执行外部程序 支持四个内建命令,名称和功能为: quit:退 ...

  5. DataX异构数据源离线同步工具json文件配置说明

    DataX 是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.ODPS.HBase.FTP等各种异构数据源之间稳定高效的数据同步功能 ...

  6. 优先队列STL

    引入 优先队列是一种特殊的队列,它的功能是--自动排序. 基本操作: q.size(); //返回q里元素个数 q.empty(); //返回q是否为空,空则返回1,否则返回0 q.push(k); ...

  7. idea 中菜单栏定位到类的图标消失(小齿轮按钮)

    本文链接:https://www.cnblogs.com/hchengmx/p/14533349.html 在2019.2以及以下版本 勾选:Autoscroll from source: 在2019 ...

  8. 皓远的第二次博客作业(最新pta集,链表练习及期中考试总结)

    前言: 知识点运用:正则表达式,有关图形设计计算的表达式和算法,链表的相关知识,Java类的基础运用,继承.容器与多态. 题量:相较于上次作业,这几周在java方面的练习花了更多的精力和时间,所要完成 ...

  9. 《原CSharp》第二回 巧习得元素分类 子不知怀璧其罪

    第二回 巧习得元素分类 子不知怀璧其罪 ===================================================================== 云溪父亲见状看了看云 ...

  10. 实现领域驱动设计 - 使用ABP框架 - 通用准则

    在进入细节之前,让我们看看一些总体的 DDD 原则 数据库提供者 / ORM 无关性 领域和应用程序层应该与 ORM / 数据库提供程序 无关.它们应该只依赖于 Repository 接口,而 Rep ...