当前位置: 首页 > 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;已经快一年了。现在是该更新的时候了。 设计的更新 我们一直在继续完善泛型设计草案。…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...