SpringMvc源码分析-请求流程(一)

news2024/11/26 18:25:48

SpringMvc源码分析-从前端到接口请求流程

SpringMvc执行流程

其实SpringMVC请求原理很简单:说白了就是用一个DispatcherServlet 封装了一个Servlet的调度中心, 由调度中心帮我们调用我们的处理方法:在这个过程中调度中心委托给各个组件执行具体工作 ,比如帮我们映射方法请求、帮我解析参数、调用处理方法、响应数据和页面 等

在这里插入图片描述

名词解释

DispatcherServlet

它负责协调和组织不同组件完成请求处理并返回响应工作。它是SpringMVC统一的入口,所有的请求都通过它。

ViewReslover

根据ModelAndView的视图去找具体的jsp封装在View对象。

View

View是Spring MVC框架中的一个接口,它定义了如何渲染模型数据并生成响应。View对象负责将模型数据渲染为客户端可以理解的格式,例如HTML、JSON或XML等。

Handler

Handler表示请求处理器,(自己写的业务逻辑方法)。是一个Object类型的。在SpringMVC中有四种Handler:

1.实现了Controller接口的Bean对象:这是Spring MVC最初的设计,每个请求对应一个Controller对象,每个Controller只处理一个单一的动作或者请求。该方式的优点是分工明确,缺点是如果请求很多,会产生大量的Controller类,增加了代码的复杂度。在Controller的handleRequest方法中,你可以直接操作HttpServletRequest和HttpServletResponse对象来处理请求和生成响应。

//实现了Controller接口的Bean对象
@Component("/login")
public class HandlerDemo implements Controller {

   @Override
   public ModelAndView handleRequest
         (HttpServletRequest httpServletRequest,
          HttpServletResponse httpServletResponse)
         throws Exception {
      return new ModelAndView();
   }
}

2.实现了HttpRequestHandler接口的Bean对象:这是另一种处理请求的方式。相比于Controller接口,HttpRequestHandler接口提供了更多的灵活性,因为你可以直接操作ServletRequest和ServletResponse。但是,它通常只用于处理一些特定的请求,比如文件上传和下载,而不是用于处理一般的用户请求。

@Component("/login")
public class HandlerDemo implements HttpRequestHandler {
   @Override
   public void handleRequest
         (HttpServletRequest request,
          HttpServletResponse response)
         throws ServletException, IOException {
      System.out.println(1);
   }
}

3.添加了@RequestMapping注解的方法:只需要在任意一个Bean的方法上添加@RequestMapping注解,Spring MVC就会自动将这个方法映射到一个URL,然后当这个URL被请求时,Spring MVC会调用这个方法来处理请求。

@RequestMapping("/showIndex2")
public String index2(ModelAndView modelAndView) {
   modelAndView.addObject("user","zhangsan");
   return "a";
}

HandlerMapping

HandlerMapping是个接口,有不同的实现,HandlerMapping负责去寻找Handler,并且保存路径和Handler之间的映射关系。因为有不同类型的Handler,所以在SpringMVC中会由不同的HandlerMapping来负责寻找Handler,比如:

  • BeanNameUrlHandlerMapping:会把所有路径名(Bean的名称)以 “/” 开头的Bean都当作是一个Handler,BeanNameUrlHandlerMapping就会将这个Bean名称和对应的Bean实例保存到内部的一个Map结构中。然后存入到它的内部Map结构中。当接收到一个请求后,它会根据请求的URL路径去这个Map中查找对应的Handler。一般处理Controller接口和HttpRequestHandler接口
  • RequestMappingHandlerMapping:会把先把所有类上加有@Controller和@RequestMapping的bean找出来然后并解析@RequestMapping中的内容,比如method、path,封装为一个RequestMappingInfo对象,最后把RequestMappingInfo对象做为key,Method对象封装为HandlerMethod对象后作为value,存入Map。

在寻找handler的时候spring会遍历所有的HandlerMapping,挨个寻找,找到了直接返回。

HandlerAdaper

负责调用handler的具体方法,并返回试图的名称。由于我们有好几种handler,分别存放在不同的HandlerMapping中,有的handler是方法,有的是实例。

  • 实现了Controller接口的Bean对象,执行的是Bean对象中的handleRequest()
  • 实现了HttpRequestHandler接口的Bean对象,执行的是Bean对象中的handleRequest()
  • 添加了@RequestMapping注解的方法,具体为一个HandlerMethod,执行的就是当前加了注解的方法

spring在拿到handler后,它会遍历所有已注册的HandlerAdapter,调用它们的supports()方法来检查是否支持当前handler类型。如果支持,则使用该HandlerAdapter来处理请求。

可以理解为:

for(HandlerAdapter adapter : this.handlerAdapters)){
    if(adapter.supports(handler)){
        //具体执行方法逻辑,去解析Request对象,传参,执行逻辑
        adapter.handle(request,response,handler);
    }
}
//各个adapters中的supports可以理解为
public boolean supports(Object handler) {
    return (handler instanceof Controller);
 }

请求的流程:

  1. 用户发送请求到DispatcherServlet。
  2. dispatcherServlet收到请求调用处理器映射器HandlerMapping,当HandlerMapping找到一个匹配的处理程序时,它会创建一个HandlerExecutionChain对象,HandlerExecutionChain是一个包含处理程序和所有匹配的拦截器(HandlerInterceptor)的对象。拦截器可以在请求处理之前和之后执行额外的操作,最后将HandlerExecutionChain返回给dispatcherServlet。
  3. DispatcherServlet会根据处理器Handler找到处理器适配器HandlerAdaper。执行参数封装,数据格式转换,数据验证等操作
  4. HandlerAdaper执行处理器处理器Handler,并将结果ModelAndView返回给DispatcherServlet。
  5. dispatcherServlet将ModelAndView传给视图解析器ViewReslover。
  6. ViewReslover将解析ModelAndView并返回view给disatcherServlet。
  7. dispatcherServlet对view进行渲染试图。

dispatcherServlet解释请求流程

其实上述的流程都是在DispatcherServlet的doDispatch里完成的。

img

DispatcherServlet 是一个继承自 Servlet 的关键组件,因此当接收到请求时,会首先进入 Servletservice 方法,然后调用 doGet/doPost 方法,最后进入 processRequestdoService 方法,从而触发 doDispatch 方法。这个 doDispatch 方法中,执行了以下关键步骤:

1、检查请求类型:首先,会检查是否是文件上传的请求。如果是,则进行相应的处理。

processedRequest = checkMultipart(request);

2、获取handler:然后根据请求获取 HandlerExecutionChain。如果没有找到对应的处理器链,那么就会返回404错误。

HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if(mappedHandler == null){
    noHandlerFound(processedRequest, response);
    return; 
}

3、查找适配器:有了handler,就可以通过处理器找到对应的适配器 HandlerAdapter。这个适配器是 Spring MVC 中的一个关键组件,它使得 Spring MVC 可以支持多种类型的处理器,不仅仅是一个。

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

4、执行前置拦截器:这个步骤会执行所有的前置拦截器。

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

5、处理请求:然后 HandlerAdapter 会执行处理器中的一系列操作,如参数封装,数据格式转换,数据验证等。

ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

6、设置默认视图:如果 ModelAndView 中没有设置视图,那么这里会为其设置一个默认视图。

applyDefaultViewName(processedRequest, mv);

7、执行后置处理器:在处理完请求后,这个步骤会执行所有的后置处理器。

mappedHandler.applyPostHandle(processedRequest, response, mv);

8、渲染视图并响应用户:最后,DispatcherServlet 会将 ModelAndView 对象传给 ViewReslover 视图解析器进行解析,得到具体的视图对象,并进行视图渲染,最后响应给用户。

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

接下来的内容,我们将更深入地探索 Spring MVC 的工作机制,比如Tomcat启动后Spring MVC是如何创建的,handlerMapping 是如何找到对应的处理器的,adapter 是如何处理处理器的,以及 SPI 如何实现 Spring MVC 的。
ler, mv, dispatchException);


接下来的内容,我们将更深入地探索 Spring MVC 的工作机制,比如Tomcat启动后Spring MVC是如何创建的,`handlerMapping` 是如何找到对应的处理器的,`adapter` 是如何处理处理器的,以及 SPI 如何实现 Spring MVC 的。

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

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

相关文章

【Nginx32】Nginx学习:随机索引、真实IP处理与来源处理模块

Nginx学习:随机索引、真实IP处理与来源处理模块 完成了代理这个大模块的学习,我们继续其它 Nginx 中 HTTP 相关的模块学习。今天的内容都比较简单,不过最后的来源处理非常有用,可以帮我们解决外链问题。另外两个其实大家了解一下就…

登录中获取验证码的节流

一. 验证码框 <el-input placeholder"请输入验证码" prefix-icon"el-icon-lock" v-model"ruleForm.code"><el-button slot"suffix" :disabled"disabled" type"text" size"mini" click"ch…

树莓派玩转openwrt软路由:5.OpenWrt防火墙配置及SSH连接

1、SSH配置 打开System -> Administration&#xff0c;打开SSH Access将Interface配置成unspecified。 如果选中其他的接口表示仅在给定接口上侦听&#xff0c;如果未指定&#xff0c;则在所有接口上侦听。在未指定下&#xff0c;所有的接口均可通过SSH访问认证。 2、防火…

ideal远程Debug部署在服务器上的服务详解

ideal远程Debug部署在服务器上的服务详解 一 简介二 ideal配置步骤第一步&#xff1a;点击Edit Configurations选项添加远程连接第二步&#xff1a;配置Remote JVM debug参数第三步&#xff1a;服务的启动参数中添加第二步生成的命令并重新启动服务第四步&#xff1a;ideal启动…

联想电脑一键重装系统Win10操作方法

很多用户都会利用重装系统的方法&#xff0c;来解决系统崩溃、病毒感染等问题。但是&#xff0c;很多新手用户不知道联想电脑Win10系统重装的详细方法步骤&#xff0c;下面小编给大家详细介绍关于联想电脑Win10系统重装的操作方法&#xff0c;帮助大家轻松快速地完成系统的重装…

比postman更好用的接口管理软件——Apifox

比postman更好用的接口管理软件——Apifox 官网安装和登录Apifox功能使用团队管理&项目管理接口管理接口文档 Apifox 帮助文档 最近使用了一个好用的中文版接口管理软件&#xff0c;Apifox&#xff0c;以下介绍一下它的使用方式及好处。 官网 Apifox的官方地址&#xff1a…

微服务13-Seata的四种分布式事务模式

文章目录 XA模式实现XA模式 AT模式AT模式的脏写问题&#xff08;对同数据并发写的问题&#xff09;其他事务不获取全局锁的一个情况&#xff08;AT模式写隔离的实现&#xff09;实现AT模式 TCC模式TCC实现我们怎么样去判断是否空回滚和业务悬挂&#xff1f;业务分析 Saga模式总…

C++学习——C++函数的编译、成员函数的调用、this指针详解

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 从博文的分析中可以看出&#xff0c;对象的内存中只保留了成员变量&#xff0c;除此之外没有任何其他信息&#xff0c;程序运行时不知道 stu 的类型为 Student&#xff0c;也不知道它…

基于nodejs+vue校园失物招领平台设计与实现

科学技术日新月异的如今&#xff0c;计算机在生活各个领域都占有重要的作用&#xff0c;尤其在信息管理方面&#xff0c;在这样的大背景下&#xff0c;学习计算机知识不仅仅是为了掌握一种技能&#xff0c;更重要的是能够让它真正地使用到实目 录 摘 要 I ABSTRACT II 目 录 II…

数据库系统概论学习 1 绪论

1.1.1 数据、数据库、数据库管理系统、数据库系统 一、数据 Data 数据是数据库中存储的基本对象 定义&#xff1a;描述事物的符号记录称为数据&#xff0c;描述事物的符号可以是数字、文字、图像、图形、声音、语言等表现形式&#xff0c;它们都可以经过数字化后存入计算机。…

六分科技CEO李阳:精准定位助力汽车智能化普及

10月10日&#xff0c;2023四维图新用户大会在上海成功举办。大会现场&#xff0c;六分科技展示了基于PPP-RTK技术的“星璨”产品和软硬件一体化解决方案。同时在智能驾驶主题论坛上&#xff0c;六分科技CEO李阳受邀发表了以《精准定位助力汽车智能化普及》为主题的演讲。 高精度…

微信小程序clearInterval无法关闭时间间隔器问题解决

今天在微信小程序遇到了一个问题 我的代码是这样的 // 关闭动画函数 AnimationOff() {//定义时间间隔器clearInterval(this.animationTimer) }, DefineAnimation() {//定义时间间隔器this.animationTimer setInterval(() > {console.log("执行");}, 1000) },但是…

【Power BI】Power BI 入门指南:版本、下载和报表创建的步骤

文章目录 一、前言二、了解 Power BI 版本三、下载 Power BI Desktop四、如何开始使用 Power BI Desktop五、在 Power BI Desktop 中创建报表六、文末总结 一、前言 Power BI 是微软于 2013 年推出的产品&#xff0c;为一款商业智能与数据可视化工具。它通过引人注目的视觉效果…

企业如何选择安全又稳定的文件传输协议

企业无论是内部的数据共享&#xff0c;还是与外部的合作交流&#xff0c;都需要通过网络进行文件的传输和交换。然而&#xff0c;文件传输它涉及到多方面的因素&#xff0c;例如文件的大小、数量、类型、敏感性、传输距离、网络环境等。这些因素都会影响到文件传输的各个方面&a…

WEB应用程序编程接口API

使用Web API Web API是网站的一部分&#xff0c;用于与使用具体URL请求特定信息的程序交互。这种请求称为API调用。请求的数据格式以易于处理的格式&#xff08;JSON,CSV&#xff09;返回。 Git和GitHub Git是一个分布式版本控制系统&#xff0c;帮助人们管理为项目所做的工作…

Intellij 安装配置 lombok

Intellij 安装配置 lombok 用 lombok 能够减少 setter/getter/noArgsConstructor 这样的 boilerplate 代码&#xff0c;所以用起来还是比较方便的。 刚开始以为直接安装到 maven 里面就能用了&#xff0c;运行的时候发现 Getter, Data 这些 annotation 根本找不到&#xff0c…

*常用函数

文章目录 nn.PReLU() 激活函数 nn.PReLU() 激活函数 PReLU(Parametric Rectified Linear Unit), 顾名思义&#xff1a;带参数的ReLU 其中a代表的是可学习的参数 ReLU、PReLU的比较&#xff1a; 如果ai0&#xff0c;那么PReLU退化为ReLU&#xff1b; 如果ai是一个很小的固定…

c++可变参数模板

不要做一个清醒的堕落者文章目录 可变参数模板的简介什么是可变参数 模板参数包参数包数据的获取(函数递归获取)参数包的获取(逗号表达式获取) 可变参数的应用emplace 可变参数模板的简介 c11添加的新特性能够让你创建可以接受改变的函数模板和类模板&#xff0c;C98/03&#…

深入篇【C++】总结<lambda表达式>与<包装器和bind>的使用与意义

深入篇【C】总结&#xff1c;lambda表达式&#xff1e;与&#xff1c;包装器和bind&#xff1e;的使用与意义 一.lambda表达式1.使用语法2.底层本质3.应用意义 二.包装器(适配器)1.使用语法2.解决问题①3.解决问题②4.应用场景:指令操作 三.bind (适配器)1.调整参数位置2.绑定参…

Kafka基础入门

Kafka介绍 Kafka是什么&#xff1f; kafka是一种分布式的&#xff0c;基于发布/订阅的消息系统。 Kafka的特点 分布式&#xff0c;吞吐量高&#xff0c;发布订阅模式&#xff0c;轻量灵活&#xff0c;较长时间持久化 Kafka的应用场景 解耦 原先一个微服务是通过接口&…