当前位置: 首页 > news >正文

Spring MVC 启动之 HandlerMapping

        在上一篇文章中,我们介绍了 Spring MVC 的启动流程,接下来我们将发分多个篇章详细介绍流程中的重点步骤

d.png

        今天我们从 HandlerMapping 开始分析,HandlerMapping 是框架中的一个非常重要的组件。它的作用是将URL请求映射到合适的处理程序(Handler)上,这样就能够实现控制器与页面之间的交互。在 Spring MVC 中,有多种不同的 HandlerMapping 实现,本文将对这些实现的作用和源码原理进行详细介绍。

作用

在 Spring MVC 框架中,HandlerMapping 是一个非常重要的组件,它的作用是将URL请求映射到相应的处理程序上。具体来说,HandlerMapping 会根据URL请求的路径、请求参数等信息,确定需要执行哪个处理程序,并将该处理程序返回给 DispatcherServlet。然后 DispatcherServlet 再将请求分配给相应的处理程序,处理程序处理完请求后,将结果返回给 DispatcherServlet,DispatcherServlet 再将结果返回给客户端。

c.png

HandlerMapping的实现

        Spring MVC 框架中有多种不同的 HandlerMapping 实现,每种实现都有不同的作用和使用场景。下面将逐一介绍这些实现。

BeanNameUrlHandlerMapping

        BeanNameUrlHandlerMapping 是 Spring MVC 框架中最简单的 HandlerMapping 实现,它的作用是将 URL 请求的路径映射到 Bean 的名称上。具体来说,当请求的路径与一个 Bean 的名称匹配时,BeanNameUrlHandlerMapping 会将该请求映射到对应的 Bean 上。

例如:

  1. 假设有一个名为 “/hello” 的请求
  2. 我们可以在 Spring 配置文件中定义一个名为 “helloController” 的 Bean
  3. 然后使用 BeanNameUrlHandlerMapping 将 “/hello” 请求映射到该 Bean 上

这样,当客户端发送 “/hello” 请求时,DispatcherServlet 就会将该请求分配给 “helloController” 处理。

BeanNameUrlHandlerMapping 的源码比较简单,它的核心代码如下所示:

public class BeanNameUrlHandlerMapping extends AbstractUrlHandlerMapping {protected Object getHandlerInternal(HttpServletRequest request) throws Exception {String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);return obtainHandler(lookupPath, request);}
}

        从代码中可以看出,BeanNameUrlHandlerMapping 实现了 AbstractUrlHandlerMapping 接口,并重写了其中的 getHandlerInternal 方法。该方法的作用是根据请求的 URL 路径查找相应的处理程序

SimpleUrlHandlerMapping

SimpleUrlHandlerMapping 是 Spring MVC 框架中另一种常用的 HandlerMapping 实现,它的作用是将 URL 请求的路径映射到处理程序上。与 BeanNameUrlHandlerMapping 不同的是,SimpleUrlHandlerMapping 可以将一个URL请求映射到多个处理程序上

例如:

  1. 假设有两个请求 “/hello” 和 “/world”
  2. 我们可以使用 SimpleUrlHandlerMapping 将这两个请求分别映射到不同的处理程序上。具体来说,我们可以在 Spring 配置文件中定义多个 Bean,并分别为它们设置不同的URL路径。
  3. 然后使用 SimpleUrlHandlerMapping 将这些URL路径与相应的处理程序进行映射。

这样,当客户端发送一个请求时,SimpleUrlHandlerMapping 就会根据请求的URL路径查找相应的处理程序,并将请求分配给该处理程序处理。

SimpleUrlHandlerMapping 的源码也比较简单,它的核心代码如下所示:

public class SimpleUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {protected Object getHandlerInternal(HttpServletRequest request) throws Exception {String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);Object handler = lookupHandler(lookupPath, request);if (handler == null) {handler = getDefaultHandler();}return handler;}
}

        从代码中可以看出,SimpleUrlHandlerMapping 同样实现了 AbstractUrlHandlerMapping 接口(在 AbstractDetectingUrlHandlerMapping 中继承),并重写了其中的 getHandlerInternal 方法。该方法的作用是根据请求的URL路径查找相应的处理程序。

ControllerClassNameHandlerMapping

        ControllerClassNameHandlerMapping 是Spring MVC 框架中一种比较特殊的 HandlerMapping 实现,它的作用是将URL请求的路径映射到 Controller 类名上。具体来说,ControllerClassNameHandlerMapping 会根据请求的URL路径查找对应的 Controller 类名,并将该类返回给 DispatcherServlet,然后 DispatcherServlet 再将请求分配给该 Controller 类处理。

例如:

  1. 假设有一个名为 “/hello” 的请求
  2. 我们可以定义一个名为 HelloController的Controller 类
  3. 使用 ControllerClassNameHandlerMapping 将 “/hello” 请求映射到该类上。

这样,当客户端发送 “/hello” 请求时,ControllerClassNameHandlerMapping 就会将该请求映射到 HelloController 处理。

ControllerClassNameHandlerMapping 的源码也比较简单,它的核心代码如下所示:

public class ControllerClassNameHandlerMapping extends AbstractControllerUrlHandlerMapping {protected Object getHandlerInternal(HttpServletRequest request) throws Exception {String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);String controllerClassName = getClassNameForUrlPath(lookupPath);return obtainApplicationContext().getBean(controllerClassName);}
}

        从代码中可以看出,ControllerClassNameHandlerMapping 同样实现了 AbstractUrlHandlerMapping 接口,并重写了其中的 getHandlerInternal 方法。该方法的作用是根据请求的URL路径查找相应的 Controller 类名,并将该类返回给 DispatcherServlet。

DefaultAnnotationHandlerMapping

        DefaultAnnotationHandlerMapping 是Spring MVC 框架中另一种比较常用的 HandlerMapping实 现,它的作用是将 URL 请求的路径映射到标注了 @RequestMapping 注解的方法上

        具体来说,DefaultAnnotationHandlerMapping 会扫描应用程序中所有标注了 @RequestMapping 注解的方法,并将这些方法与相应的URL路径进行映射。

        然后当客户端发送一个请求时,DefaultAnnotationHandlerMapping 就会根据请求的URL路径查找相应的处理程序,并将该处理程序返回给 DispatcherServlet,然后 DispatcherServlet 再将请求分配给该处理程序处理。

例如:

  1. 假设有一个名为 “/hello” 的请求
  2. 我们可以在 Controller 类的某个方法上标注 @RequestMapping 注解
  3. 将该方法与 “/hello” 请求进行映射。

这样,当客户端发送 “/hello” 请求时,DefaultAnnotationHandlerMapping 就会将该请求映射到该方法上,然后将该方法返回给 DispatcherServlet 处理。

DefaultAnnotationHandlerMapping 的源码比较复杂,因为它需要扫描应用程序中所有标注了 @RequestMapping 注解的方法。其核心代码如下所示:

public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping implements BeanFactoryAware, InitializingBean {private final List<RequestMappingInfoHandlerMapping> handlerMappings = new ArrayList<>();protected Object getHandlerInternal(HttpServletRequest request) throws Exception {for (RequestMappingInfoHandlerMapping hm : this.handlerMappings) {HandlerExecutionChain handler = hm.getHandler(request);if (handler != null) {return handler;}}return null;}public void afterPropertiesSet() throws Exception {initHandlerMethods();}protected void initHandlerMethods() {detectHandlerMethods();if (logger.isInfoEnabled()) {logger.info("Mapped " + this.handlerMethods.size() + " request handler methods");}}protected void detectHandlerMethods() {...}
}

        从代码中可以看出,DefaultAnnotationHandlerMapping 同样实现了 AbstractUrlHandlerMapping 接口,并重写了其中的 getHandlerInternal 方法。该方法的作用是根据请求的 URL 路径查找相应的处理程序。

        与其他 HandlerMapping 不同的是,DefaultAnnotationHandlerMapping 还实现了 BeanFactoryAware和InitializingBean 接口,以便在初始化时扫描应用程序中所有标注了 @RequestMapping 注解的方法。

        具体来说,它会调用 detectHandlerMethods 方法,对应用程序中所有标注了 @RequestMapping 注解的方法进行扫描,并将这些方法与相应的URL路径进行映射。

总结

        在 Spring MVC 框架中,HandlerMapping 用于将URL请求的路径映射到相应的处理程序上。框架中提供了多种不同的 HandlerMapping 实现,包括 BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、ControllerClassNameHandlerMapping 和 DefaultAnnotationHandlerMapping 等。不同的HandlerMapping 实现方式适用于不同的应用场景。

  • BeanNameUrlHandlerMapping 是最简单的HandlerMapping实现,它将 URL 请求的路径直接映射到 Bean 的名称上。
  • SimpleUrlHandlerMapping 则将 URL 请求的路径与相应的处理程序进行映射。
  • ControllerClassNameHandlerMapping 将 URL 请求的路径映射到 Controller 类名上。
  • DefaultAnnotationHandlerMapping 则将 URL 请求的路径映射到标注了 @RequestMapping 注解的方法上。

无论是哪种 HandlerMapping 实现方式,它们都遵循相同的流程来处理请求。具体来说,它们的流程如下:

客户端发送请求到DispatcherServlet。

  1. DispatcherServlet根据请求的URL路径选择相应的HandlerMapping。
  2. HandlerMapping将请求的URL路径与相应的处理程序进行映射。
  3. HandlerMapping返回相应的处理程序。
  4. DispatcherServlet将请求交给相应的处理程序进行处理。
  5. 处理程序进行业务逻辑的处理,并返回相应的结果。
  6. DispatcherServlet将处理程序的结果进行封装,并返回给客户端。

相关文章:

Spring MVC 启动之 HandlerMapping

在上一篇文章中&#xff0c;我们介绍了 Spring MVC 的启动流程&#xff0c;接下来我们将发分多个篇章详细介绍流程中的重点步骤 今天我们从 HandlerMapping 开始分析&#xff0c;HandlerMapping 是框架中的一个非常重要的组件。它的作用是将URL请求映射到合适的处理程序&#x…...

基于YOLOv5的停车位检测系统(清新UI+深度学习+训练数据集)

摘要&#xff1a;基于YOLOv5的停车位检测系统用于露天停车场车位检测&#xff0c;应用深度学习技术检测停车位是否占用&#xff0c;以辅助停车场对车位进行智能化管理。在介绍算法原理的同时&#xff0c;给出Python的实现代码、训练数据集以及PyQt的UI界面。博文提供了完整的Py…...

【Linux系统编程】5.vim基本操作命令

目录 跳转到指定行 命令模式 末行模式 跳转行首 跳转行尾 自动格式化代码 大括号、中括号、小括号对应 光标移至行首 光标移至行尾 删除单个字符 删除一个单词 删除光标至行尾 删除光标至行首 替换单个字符 删除指定区域 删除指定1行 删除指定多行 复制一行 …...

主流机器学习平台调研与对比分析

梗概 本报告主要调研目前主流的机器学习平台&#xff0c;包括但不限于Amazon的Sage maker&#xff0c;Alibaba的PAI&#xff0c;Baidu的PaddlePaddle。对产品的定位、功能、实践、定价四个方面进行详细解析&#xff0c;并通过标杆对比分析提出一套机器学习平台评价体系&#x…...

作业帮基于明道云开展的硬件业务数字化建设

今天由我代表作业帮来介绍公司在低代码平台应用的一些经验和心得。我今天分享的内容包含两部分&#xff0c;一个是作业帮硬件的介绍&#xff0c;另一个是基于明道云的系统能力建设&#xff0c;也是我们自己总结的经验&#xff0c;希望能给大家带来一些启发。 一、关于作业帮 …...

位图及布隆过滤器的模拟实现与面试题

位图 模拟实现 namespace yyq {template<size_t N>class bitset{public:bitset(){_bits.resize(N / 8 1, 0);//_bits.resize((N >> 3) 1, 0);}void set(size_t x)//将某位做标记{size_t i x / 8; //第几个char对象size_t j x % 8; //这个char对象的第几个比特…...

在 Python 中将天数添加到日期

使用 datetime 模块中的 timedelta() 方法将天数添加到日期中&#xff0c;例如 result_1 date_1 timedelta(days3)。 timedelta 方法可以传递天数参数并将指定的天数添加到日期。 from datetime import datetime, date, timedelta# ✅ 将天数添加到日期 my_str 09-24-2023 …...

vue3知识点

一、vue3带来了什么&#xff1f; 1.性能的提升 打包大小减少41% 初次渲染快55%&#xff0c;更新渲染快133% 内存减少54% 2.源码的升级 使用Proxy代替defineProperty实现响应式 重写虚拟DOM的实现和Tree-shaking 3.拥抱TypeScript Vue3可以更好的支持TypeScript 4.新的特性 4.1.…...

一行代码生成Tableau可视化图表

今天给大家介绍一个十分好用的Python模块&#xff0c;用来给数据集做一个初步的探索性数据分析(EDA)&#xff0c;有着类似Tableau的可视化界面&#xff0c;我们通过对于字段的拖拽就可以实现想要的可视化图表&#xff0c;使用起来十分的简单且容易上手&#xff0c;学习成本低&a…...

链表——删除元素或插入元素(头插法及尾插法)

目录 链表的结点由一个结构体构成 判断链表是否为空 键盘输入链表中的数据 输出链表中的数据 返回链表的元素个数 清空链表 返回指定位置的元素值 查找数据所在位置 删除链表的元素 插入元素 建立无头结点的单链表 建立有头结点的单链表&#xff08;头插法&#xff…...

oracle容器的使用

oracle容器的使用 1.下载oracle容器 1.1拉取容器 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g拉取国内镜像&#xff0c;该镜像大小为2.99G&#xff0c;已经集成了oracle环境&#xff0c;拉取完可以直接用&#xff0c;推荐使用这款oracle镜像 1.2查看…...

基于springboot会员制医疗预约服务管理信息系统演示【附项目源码】

基于springboot会员制医疗预约服务管理信息系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea M…...

GoogleAdsense国内加载慢怎么解决?

一淘模板 56admin.com 发现GoogleAdsense&#xff08;谷歌广告联盟&#xff09;国内加载慢拖网站速度怎么解决&#xff1f;GoogleAdsense是谷歌旗下的站长广告联盟系统&#xff0c;如果站长没有好的变现渠道&#xff0c;挂谷歌联盟是最好的选择&#xff08;日积月累&#xff09…...

【MySQL专题】03、性能优化之读写分离(MaxScale)

在我们了解了MySQL的主从复制的性能优化之后&#xff0c;紧接着《【MySQL专题】02、性能优化之主从复制》中&#xff0c;我们提及的读写分离&#xff0c;来进行读操作和写操作分散到不同的服务器结构中&#xff0c;同时希望对多个从服务器能提供负载均衡&#xff0c;读写分离和…...

Redis7高级之BigKey(二)

1.MoreKey案例 往redis里面插入大量测试数据key 生成100W条redis批量设置kv的语句保存在redisTest.txt for((i1;i<100*10000;i)); do echo "set k$i v$i" >> /tmp/redisTest.txt ;done; # 生成100W条redis批量设置kv的语句(keykn,valuevn)写入到/tmp目录下的…...

flex弹性盒子

概念 弹性盒子是一种用于按行或者按列布局的一维布局方法&#xff0c;元素可以膨胀以填充额外的空间&#xff0c;缩小以适应更小的空间 以下属性是给父元素添加的 1.flex-direction --改变轴的方向 row 默认值 默认沿着x轴排版(横向从左到右排列&#xff08;左对齐&#xff…...

[Java Web]Cookie | 一文详细介绍会话跟踪技术中的Cookie

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Java Web 目录Cookie1、工作原理2、如何使用2.1、发送Cookie2.2、获取Cookie3、Cookie的存活时间4、中文错误Coo…...

这可能是2023最全的Java面试八股文,共计1658页,Java技术手册的天花板

前两天有个小伙伴在后台留言&#xff0c;最近的面试越来越难了&#xff0c;尤其是技术面&#xff0c;考察得越来越细&#xff0c;越来越底层&#xff0c;庆幸的是最终顺利找到了工作。 一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识 比如果这样的问题…...

字节流及存放本地文件上传和下载文件

前言 之前的文章有写过 vuespringboot使用文件流实现文件下载 实现如何通过 D:\file\文件名.文件格式的形式进行下载文件 但是它对于很多业务场景相对适用性不是很广泛。 以及 elementUI加springboot实现上传excel文件给后端并读取excel 也只能是通过elementui的元素类型进行…...

【翻译】下一步:Go 泛型

原文地址&#xff1a; The Next Step for Generics - The Go Blog https://blog.golang.org/generics-next-step 介绍 自从我们上次写下关于在Go中加入泛型的可能性的文章以来&#xff0c;已经快一年了。现在是该更新的时候了。 设计的更新 我们一直在继续完善泛型设计草案。…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...