带着问题阅读源码——Spring MVC是如何将url注册到RequestMappingHandlerMapping?

背景

在 Spring MVC 中,DispatcherServlet 是前端控制器(front controller),它负责接收所有的 HTTP 请求并将它们映射到相应的处理器(handler)。为了实现这一点,Spring MVC 使用了适配器模式将 Controller 与 DispatcherServlet 绑定在一起。

在Spring MVC的优雅设计中,所有公开的接口默认都通过RequestMappingHandlerMapping进行映射转换。这一过程的核心在于如何将这些接口有效地注册到RequestMappingHandlerMapping。本文将深入探讨这一机制,揭开其背后的原理和细节,这是我们研究的主要焦点。

RequestMappingHandlerMapping介绍

RequestMappingHandlerMapping 是 Spring MVC 中的一个类,用于将请求映射到处理器方法。它是 AbstractHandlerMethodMapping 的一个具体实现,提供了一些默认的请求映射策略。

在 Spring MVC 中,HandlerMapping 负责将请求映射到相应的处理器方法。RequestMappingHandlerMapping 提供了一个基本的框架,可以自定义扩展以支持不同的请求映射方式。例如,可以通过继承RequestMappingHandlerMapping 并重写其中的方法来实现自定义的请求映射策略。

具体来说,RequestMappingHandlerMapping 主要包含以下几个关键部分:

  • registerHandlerMethod 方法:该方法用于注册一个处理器方法。它首先检查该处理器方法是否已经注册过,如果没有则将其添加到内部维护的处理器方法列表中。

  • getHandlerInternal 方法:该方法根据请求信息获取对应的处理器方法。它首先通过lookupHandlerMethod 方法查找匹配的处理器方法,然后通过 instantiateHandlerMethod 方法实例化处理器方法对象。

  • lookupHandlerMethod 方法:该方法根据请求信息查找匹配的处理器方法。它首先通过extractPathWithinApplication 方法提取请求路径中的应用程序路径,然后通过 matches 方法匹配处理器方法。如果找到匹配的处理器方法,则返回该处理器方法;否则返回 null。

  • matches 数组:该方法根据请求信息和处理器方法进行匹配。它首先检查请求路径是否与处理器方法的 URL 模式匹配,然后检查请求方法是否与处理器方法的 HTTP 方法匹配。如果两个条件都满足,则认为匹配成功。

  • handleMatch 方法:该方法处理匹配成功的处理器方法。它首先调用 preHandle 方法进行预处理,然后调用处理器方法执行业务逻辑,最后调用 afterCompletion 方法进行后处理。

注册过程

AbstractHandlerMethodMapping是Spring MVC中用于处理请求映射的抽象类。它提供了一些基本的方法,如获取处理器方法、处理方法参数等。具体的实现类需要继承这个抽象类并实现相应的方法。

AbstractHandlerMethodMapping 中的 detectHandlerMethods 方法是用于从处理器中获取处理器方法并注册的。这个方法是一个受保护的方法,它的作用是检测带有特定注解(如@RequestMapping)的方法,并将这些方法注册到映射器中,以便后续可以根据请求找到对应的处理器方法来处理请求。

具体来说,detectHandlerMethods 方法会执行以下步骤:

  • 获取handler的类型:如果传入的handler是字符串类型,则将其转换为对应的类类型。
	Class<?> handlerType = (handler instanceof String ?obtainApplicationContext().getType((String) handler) : handler.getClass());
  • 检测handler的方法:遍历handler的所有方法,检测哪些方法带有特定的注解(如@RequestMapping),这些方法被视为处理器方法。
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup<T>) method -> {try {return getMappingForMethod(method, userType);}catch (Throwable ex) {throw new IllegalStateException("Invalid mapping on handler class [" +userType.getName() + "]: " + method, ex);}});
  • 注册处理器方法:将检测到的处理器方法注册到映射器中,这样当接收到请求时,映射器就可以根据请求的信息找到对应的处理器方法来处理请求。
			methods.forEach((method, mapping) -> {Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);registerHandlerMethod(handler, invocableMethod, mapping);});}

调用过程

在这里插入图片描述

在 Spring MVC 中,RequestMappingHandlerMapping 是负责处理基于注解的控制器方法的映射。默认情况下,所有标记有 @RequestMapping 注解的控制器方法都会通过 RequestMappingHandlerMapping 进行注册和处理。这个过程涉及到以下几个关键步骤:

  1. Spring容器启动:
  • 在应用启动时,Spring 容器会初始化所有的单例 Bean,包括 DispatcherServlet 和相关的组件。
  1. 初始化 RequestMappingHandlerMapping:
  • RequestMappingHandlerMapping 实现了 InitializingBean 接口,因此它的 afterPropertiesSet() 方法会在所有属性设置完成后被调用,以完成其初始化工作。
  1. 扫描控制器组件:
  • 在初始化过程中,RequestMappingHandlerMapping 会扫描 Spring 容器中的 Bean,寻找带有 @Controller 注解的类以及带有 @RequestMapping 注解的方法。
  1. 注册映射关系:
  • 对于找到的控制器和方法,RequestMappingHandlerMapping 会将它们的 URL 路径和处理方法之间的映射关系注册到内部的映射注册表中。
  1. 构建URL到方法的映射:
  • RequestMappingHandlerMapping 会解析这些映射信息,构建一个从 URL 到控制器方法的映射表,以便能够快速地根据请求的 URL 找到对应的处理方法。
  1. 处理请求:
  • 当 HTTP 请求到达 DispatcherServlet 时,它会使用 RequestMappingHandlerMapping 来确定请求应该由哪个控制器方法来处理。一旦找到匹配的方法,DispatcherServlet 会使用 RequestMappingHandlerAdapter 来执行该方法。
  1. 适配器模式的应用:
  • 适配器模式在这里确保了 DispatcherServlet 能够通过统一的 HandlerAdapter 接口来执行不同类型的处理器,而不需要了解具体的实现细节。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713416.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大街款商城项目03-微服务之间调用

目录 RestTemplate OpenFeign 1.引入依赖open-feign 2.声明要调用的服务和接口 3.注入FeignClient启用 4验证 RestTemplate 在微服务架构中&#xff0c;使用RestTemplate是一种常见的方式进行服务间的HTTP通信。以下是一个简单的示例&#xff0c;演示如何使用RestTempla…

Android minigbm框架普法

Android minigbm框架普法 引言 假设存在这么一个场景&#xff0c;我的GPU的上层实现走的不是标准的Mesa接口&#xff0c;且GPU也没有提专门配套的gralloc和hwcompoer实现。那么我们的Android要怎么使用到EGL和GLES库呢&#xff0c;并且此GPU驱动是支持drm实现的&#xff0c;也有…

Galaxy生信云平台:集合操作工具大全

Galaxy平台上的文件称为数据集&#xff08;Dataset&#xff09;&#xff0c;如果将多个文件组合在一起&#xff0c;则形成数据集合&#xff08;Dataset collection&#xff09;。 上传文件后&#xff0c;可以通过工具将文件构建成数据集合。具体操作可以参考前面介绍转录组流程…

后台组件体系

从今天开始进入更细粒度说明。后台微服务是由组件构成的。平台的开发理念是为甲方打造一个生态环境。安装实施时为客户安装私仓来管理组件。开发微服务时鼓励拆分为组件。开发新功能时&#xff0c;先看有没有相关组件&#xff0c;有的话就在pom.xml文件&#xff08;不要问我这个…

Day10:基础入门-HTTP数据包Postman构造请求方法请求头修改状态码判断

目录 数据-方法&头部&状态码 案例-文件探针 案例-登录爆破 工具-Postman自构造使用 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服务/负载均衡等 安全产品&#xff1a;CDN/WAF/IDS/IPS/蜜罐/防火墙/杀毒等 渗透命令&#xff1a;文件…

什么是端点安全以及如何保护端点

什么是端点安全 端点是指可以接收信号的任何设备&#xff0c;是员工使用的一种计算设备&#xff0c;用于保存公司数据或可以访问 Internet。端点的几个示例包括&#xff1a;服务器、工作站&#xff08;台式机和笔记本电脑&#xff09;、移动设备、虚拟机、平板电脑、物联网、可…

一【初识EMC】

在作为硬件行业相关从业者&#xff0c;经常接触到EMC相关问题&#xff0c;下面来简单介绍下EMC相关方面的知识 文章目录 前言一、生活中的EMC现象&#xff1f;二、EMC是什么三、EMC的三要素四、EMI与EMS的评估方式1.RE2.CE3.HAR4.FLICKER5.Rs6.CS7.ESD8.EFT9.DIP10.PMS11.surge…

Zookeeper3:客户端命令

文章目录 客户端命令连接服务端Zookeeper客户端内置命令 ls - 节点信息 客户端命令 连接服务端Zookeeper //客户端连接服务端zookeeper 默认连的本机2181端口的zookeeper cd /opt/module/zookeeper-3.9.1/bin && sh zkCli.sh//客户端连接远程服务端zookeeper cd /op…

【小尘送书-第十一期】编程的基石,开发的核心:《算法秘籍》

大家好&#xff0c;我是小尘&#xff0c;欢迎你的关注&#xff01;大家可以一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的工作&#xff01; &#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 &#x1…

如何使用GAP-Burp-Extension扫描潜在的参数和节点

关于GAP-Burp-Extension GAP-Burp-Extension是一款功能强大的Burp扩展&#xff0c;该工具在getAllParams扩展的基础上进行了升级&#xff0c;该工具不仅可以帮助广大研究人员在安全审计过程中扫描潜在的参数&#xff0c;而且还可以搜索潜在的链接并使用这些参数进行测试&#…

零基础如何快速入门伦敦金交易

伦敦金交易是金融市场中备受关注的一种投资方式。对于想要学习如何炒伦敦金并快速开始交易的人来说&#xff0c;本文将为您提供一份全面而详细的指南。无论您是初学者还是有经验的交易者&#xff0c;本文都将帮助您了解伦敦金交易的基本知识&#xff0c;并提供一些实用的技巧和…

协议-http协议-基础概念03-http状态码-http特点-http性能-压缩和分块传输-范围请求

参考来源&#xff1a; 极客时间-透视HTTP协议(作者&#xff1a;罗剑锋)&#xff1b; 01-状态码分类 开头的 Version 部分是 HTTP 协议的版本号&#xff0c;通常是HTTP/1.1&#xff0c;用处不是很大。后面的 Reason 部分是原因短语&#xff0c;是状态码的简短文字描述&#xff…

每周一算法:双向广搜

题目链接 字符串变换 题目描述 已知有两个字串 A , B A,B A,B&#xff0c;及一组字串变换的规则&#xff08;至多 6 6 6个规则&#xff09;: A 1 → B 1 A_1→B_1 A1​→B1​ A 2 → B 2 A_2→B_2 A2​→B2​ … 规则的含义为&#xff1a;在 A A A中的子串 A 1 A_1 A1​…

pytorch统计属性

目录 1.normal2. mean, sum, min, max, prod3.argmin, argmax4. topk kthvalue5. compare 1.normal torch.normal(mean, std, *, generatorNone, outNone) → Tensor返回一个张量&#xff0c;其中的每个元素随机来自独立的标准正态分布。这些分布具有给定的均值和标准差。 参数…

【cmu15445c++入门】(13)C++的std::promise

一、说明 std::promise 是C11并发编程中常用的一个类&#xff0c;常配合std::future使用。其作用是在一个线程t1中保存一个类型typename T的值&#xff0c;可供相绑定的std::future对象在另一线程t2中获取 二、代码 #include <chrono> #include <future> #includ…

Hive SQL 开发指南(二)使用(DDL、DML,DQL)

在大数据领域&#xff0c;Hive SQL 是一种常用的查询语言&#xff0c;用于在 Hadoop上进行数据分析和处理。为了确保代码的可读性、维护性和性能&#xff0c;制定一套规范化的 Hive SQL 开发规范至关重要。本文将介绍 Hive SQL 的基础知识&#xff0c;并提供一些规范化的开发指…

如何安装ProtoBuf环境

1 &#x1f351;下载 ProtoBuf&#x1f351; 下载 ProtoBuf 前⼀定要安装依赖库&#xff1a;autoconf automake libtool curl make g unzip 如未安装&#xff0c;安装命令如下&#xff1a; Ubuntu ⽤⼾选择&#xff1a; sudo apt-get install autoconf automake libtool cur…

Unity 向量计算、欧拉角与四元数转换、输出文本、告警、错误、修改时间、定时器、路径、

using System.Collections; using System.Collections.Generic; using UnityEngine;public class c2 : MonoBehaviour {// 定时器float t1 0;void Start(){// 向量Vector3 v1 new Vector3(0, 0, 2);Vector3 v2 new Vector3(0, 0, 3);// 计算两个向量的夹角Debug.Log(Vector3…

Java 学习和实践笔记(26):组合(component)的含义以及与继承(extends)的关系

组合的两个作用&#xff1a; 1&#xff09;通过将父类对象作为子类的属性 2&#xff09;通过第1点的作用&#xff0c;实现了代码复用。 示例代码&#xff1a; public class TestComponent {public static void main(String[] args) {Student2 s1 new Student2("jason&…

灯塔:HTML笔记

网页由哪些部分组成&#xff1f; *文字 图片 音频 视频 超链接 程序员写的代码是通过浏览器转换成网页的 五大浏览器有哪些&#xff1f; *IE浏览器 *火狐浏览器&#xff08;Firefox&#xff09; *谷歌浏览器&#xff08;Chrome&#xff09; *Safari浏览器 *欧朋浏览器&…