在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了加入注解声明

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

  3. spring启动,注册BeanDefinition,

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

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

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

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

过程如下:

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

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

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

SpringBoot中RequestMappingHandlerMapping的注入

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

环境

Springboot版本:2.4.3

过程

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

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

    1. @Bean
    2. @Primary
    3. @Override
    4. public RequestMappingHandlerMapping requestMappingHandlerMapping(
    5. @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
    6. @Qualifier("mvcConversionService") FormattingConversionService conversionService,
    7. @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    8. // Must be @Primary for MvcUriComponentsBuilder to work
    9. return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,
    10. resourceUrlProvider);
    11. }

问题

在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. 虚拟机中CentOS-7.9的硬盘空间扩容(EXSI)

    目录 一.增加虚机容量 二.创建新的分区 三.格式化新分区 四.lvm实现卷扩容 五.文件系统的扩容 大家好,我是LSF,发现一台虚机上 /dev/mapper/centos-root Use%已经快 ...

  2. redis 基础1

    1.redis是什么? redis是非关系型数据库key-value数据库,开源免费.是当下NoSQL技术之一 2.redis能干吗? (1)内存存储,可以持久化,redis存储在内存中,内存的话是断 ...

  3. 使用DSVPN解决分支网络出口为ADSL场景下的内网互通

    背景 最近接到一个项目是一家机构总部与多个分支之间的内网互通,总部具有固定ip,分部是使用adsl动态获取的不固定公网ip,由于两端互联网ip不固定所以不能使用传统的GRE技术来实现,所以最后经过评估 ...

  4. API Schema in kubernetes

    目录 什么是schema 数据库中的schema Kubernetes中的schema 通过示例了解schema 什么是schema schema一词起源于希腊语中的form或figure,但具体应该 ...

  5. 07makefile文件

    makefile 规则: 目标: 依赖 (tab)命令 第一个版本: main: main.c fun1.c fun2.c sum.c gcc -o main main.c fun1.c fun2.c ...

  6. 两个月吃透阿里P9推荐260页SpringBoot2企业应用实战pdf入职定P6+

    前言 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置 ...

  7. 用HMS Core地图服务自定义地图样式,给你的应用制作专属个性化地图

    不同行业的开发者对地图样式的展示需求差异很大.例如,物流类应用希望地图样式简洁一些,重点突出城市分布和快递路径:AR游戏类应用中的地图色彩需要和游戏UI适配,做的更酷炫一些:景区导览应用中的地图样式要 ...

  8. Unicode和中午互转

    import java.io.UnsupportedEncodingException; public class TestUnicode{ /* * 中文转unicode编码 */ public s ...

  9. 48. ResNet为什么能训练出1000层的模型

    先回顾一下resnet怎么处理它的梯度消失,使得能处理训练1000层:

  10. transforms.py

    from PIL import Image from torchvision import transforms #python的用法-->tensor数据类型 #通过transforms.To ...