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

【Spring MVC研究】DispatcherServlet如何处理请求(doDispatcher方法)

文章目录

  • 1. 最经典的MVC的使用情况
  • 2. 经典情况相关的组件
  • 3. 执行
    • 3.1. 先看DispatcherServlet的总体过程
    • 3.2. 再看`RequestMappingHandlerAdapter`的总体过程
      • 3.2.1. RequestParamMethodArgumentResolver
      • 3.2.2. 反射调用 Controller 的方法
      • 3.2.3. RequestResponseBodyMethodProcessor
  • 4. 总结

本文以“最经典”的情况分析了 DispatcherServlet 处理请求的全部过程。通读全文,读者应该对总体框架有一定的认识,且要求今后能有能力把 mvc 的其他组件原理“嵌入到总体框架中”。

1. 最经典的MVC的使用情况

这个过程很长,设计的到 web 组件很多,所以需要以一个最常见的情况作为“经典情况”来简化分析过程。突破之后再在对总体流程和框架的基础上,往上面新的补充内容。为了方便我讲解,我以:
“经典情况”是:Controller 中的@RequestMapping,方法的参数贴了@RequestParam注解,返回值上贴了@ResponseBody注解

搞完“经典情况”,后续的其他 mvc 组件作者会一个一个的分析。

2. 经典情况相关的组件

RequestMappingHandlerMapping(请求映射器

功能:把请求 request 映射到 handler;根据路径匹配
对应关系:只要我们的 Controller 写的路径匹配上了请求就可以了,假设匹配上。

HandlerMethod(处理请求

功能:具体处理请求的
对应关系:对应是 Controller 中的方法

HandlerExecutionChain(处理器链

功能:等于“处理器” + “匹配的拦截器”
对应关系:这里就是等于:“HandlerMethod + 匹配到的拦截器MappedInterceptor

RequestMappingHandlerAdapter(对HandlerExecutionChain 再次包装)

记住:反正就是由RequestMappingHandlerAdapter 开始执行的就可以了。

RequestParamMethodArgumentResolver参数解析器

功能:专门处理 @RequestParam 注解的
对应关系:从请求 request 中解析出参数(调用 ServletRequest的 getParameterValues方法)

RequestResponseBodyMethodProcessor(返回值处理器)

功能:专门刚好处理 @ResponseBody注解。

3. 执行

3.1. 先看DispatcherServlet的总体过程

DispatcherServlet 的doDispatch方法的总体执行过程:

  • getHandler(1)
  • getHandlerAdapter(2)
  • applyPreHandle(3)
  • handle(重点:真正处理)(4)
  • applyPostHandle(5)

在(1)处得到 HandlerExecutionChain,包含 HandlerMethodMappedInterceptor
在(2)处得到 RequestMappingHandlerAdapter
在(3)处,执行MappedInterceptorpreHandle方法
在(4)处,执行 RequestMappingHandlerAdapterhandler方法
在(5)处,执行MappedInterceptorpostHandle方法

3.2. 再看RequestMappingHandlerAdapter的总体过程

继续看 RequestMappingHandlerAdapterhandler方法的总体过程:

注意:执行顺序是从左到右从上到下执行的

  • 封装为ServletInvocableHandlerMethod(1)
  • invokeAndHandle
    • invokeForRequest
      • getMethodArgumentValues(解析参数)
        • resolveArgument解析参数
          • getArgumentResolver(得到“参数解析器”)
          • resolveArgument(真正解析)
      • doInvoke(具体执行)
    • handleReturnValue(处理返回值)
      • selectHandler
      • handleReturnValue
  • getModelAndView(2)

主要就只有 3 个关键过程(上面已加粗说明):
1、按 Controller 方法的要求解析参数。用的是 RequestParamMethodArgumentResolver
2、执行 Controller 方法。
3、处理 Controller 方法的返回值。用的是 RequestResponseBodyMethodProcessor
下面简单提一下其他过程(按序号):
在(1)处,把真正的执行的组件HandlerMethod 一顿疯狂包装成ServletInvocableHandlerMethod

比如就包装了 web 数据绑定器:WebDataBinder

在(2)处,处理视图,现在都是前后端开发,不用视图技术了。作者不讲,略,自己搞。

3.2.1. RequestParamMethodArgumentResolver

  • 支持的参数

在它的 supportsParameter 方法中,表明了支持“参数上贴了@RequestParam注解的参数”

  • 执行解析参数

1、 调用RequestParamMethodArgumentResolver的resolveArgument方法,
2、 会调用到RequestParamMethodArgumentResolver 的resolveName方法
3、会调用到解析文件的multipartRequest方法 和 从请求获取参数的 request.getParameterValues方法
4、解析之后还没有结束,还需要转换成 Controller 方法需要的参数类型(略,这就是另外的小细节故事了)

截止目前:也就通过从请求中获取参数完成了 Controller 方法参数的解析,

3.2.2. 反射调用 Controller 的方法

没什么好讲的,反射调用 Controller 的方法。

3.2.3. RequestResponseBodyMethodProcessor

  • 支持的类型

在supportsReturnType方法中表明了支持的类型是方法上@ResponseBody注解

  • 处理返回值

1、会调用到RequestResponseBodyMethodProcessor 的 handleReturnValue方法
2、会调用writeWithMessageConverters方法
3、最后直接调用“消息转换器”messageConverters把“返回值写到流里面去了”

注意:既然既然写到响应流 response 里面去了,响应就结束了,后面的视图处理过程就没了。

4. 总结

读完全文,读者要求掌握以下组件的工作情况。(对细节不需要苛责,但是一定要能知道** 组件的功能 ****组件在流程中的位置**

  • RequestMappingHandlerMapping(请求映射器
  • HandlerMethod(处理请求
  • HandlerExecutionChain(处理器链
  • RequestMappingHandlerAdapter(对HandlerExecutionChain 再次包装)
  • RequestParamMethodArgumentResolver(参数解析器)
  • RequestResponseBodyMethodProcessor(返回值处理器)

相关文章:

【Spring MVC研究】DispatcherServlet如何处理请求(doDispatcher方法)

文章目录 1. 最经典的MVC的使用情况2. 经典情况相关的组件3. 执行3.1. 先看DispatcherServlet的总体过程3.2. 再看RequestMappingHandlerAdapter的总体过程3.2.1. RequestParamMethodArgumentResolver3.2.2. 反射调用 Controller 的方法3.2.3. RequestResponseBodyMethodProces…...

解决github加载过慢问题

github打不开怎么办?看到这篇文章,一切都稳了! DNS被污染,一句话,修改系统hosts文件! 1.hosts文件在哪?C:\Windows\System32\drivers\etc 2.用记事本打开hosts,在最后加入以下两行…...

利用python批量处理nc数据

参考自:用Python批处理指定数据-以WRF输出结果为例演示按照指定维度合并(附示例代码)-腾讯云开发者社区-腾讯云 #下面将分别展示选择单个变量进行合并以及将所有变量按照指定维度进行合并。 #1.以单个变量P为例,可以根据需求更改,按照时间顺…...

popen() 获取 ping 命令结果解析

ref: Linux:popen() 获取 ping 命令结果 用C/C代码检测ip能否ping通(配合awk和system可以做到批量检测)_c 验证网卡能拼同-CSDN博客 Android中调用Ping操作及结果分析 - 简书 2. Linux使用ping命令查看网络延迟 - 简书...

【pytorch】深度学习准备:基本配置

深度学习中常用包 import os import numpy as np import torch import torch.nn as nn from torch.utils.data import Dataset, DataLoader import torch.optim as optimizer超参数设置 2种设置方式:将超参数直接设置在训练的代码中;用yaml、json&…...

etcd随笔

大集群 大集群主要问题有 btree重平衡和分解过程中超过20Gi的性能瓶颈,是O(n)复杂度,启动耗时增大,放大expensive request的影响。 其中最重要的就是最大程度地减少 expensive request。 对几十万级别的对象数量来说…...

0基础学习VR全景平台篇 第107篇:全景图调色和细节处理(上,地拍)

上课!全体起立~ 大家好,欢迎观看蛙色官方系列全景摄影课程! 今天教给大家的课程是地拍全景图调色和细节处理,下面我们就开始吧! 1.把照片快速导入LR软件 选择【图库】模块 打开软件后,点击【导入】按…...

Verilog功能模块——同步FIFO

前言 FIFO功能模块分两篇文章,本篇为同步FIFO,另一篇为异步FIFO,传送门: Verilog功能模块——异步FIFO-CSDN博客 同步FIFO实现起来是异步FIFO的简化版,所以,本博文不再介绍FIFO实现原理,感兴趣…...

Unity ToLua热更框架使用教程(1)

从本篇开始将为大家讲解ToLua在unity当中的使用教程。 Tolua的框架叫LuaFramework,首先附上下载链接: https://github.com/jarjin/LuaFramework_UGUI_V2 这个地址的是UGUI的。 下载完之后导入项目,首先,我们要先让这个项目跑起…...

车载相关名词--车载数据中心方案

车载数据中心方案 参考链接:https://zhuanlan.zhihu.com/p/600031042?utm_id=0 下面这张图是小鹏汽车嵌入式系统高级专家 唐黾 在同ARM一起的一个演讲稿中发布的,是一张未来车载数据中心单芯片方案构想图。主要针对的是智驾域和座舱域融合方案,下面对如上图的内外部组件及…...

helm使用

前言 类似于 Linux 的 YUM、APT,Helm 是 K8S 的包管理工具。 Helm, 一个二进制工具,用来安装、升级、卸载 K8S 中的应用程序。 Helm Chart,一个 tgz 包,类似安卓的 APK。 K8S 应用打包成 Chart,通过 He…...

Python in Visual Studio Code 2023年10月发布

排版:Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展于 2023 年 10 月发布! 此版本包括以下公告: Python 调试器扩展更新弃用 Python 3.7 支持Pylint 扩展更换时的 Lint 选项Mypy 扩展报告的范围和守护程序模式G…...

Webmin远程命令执行漏洞复现报告

漏洞编号 CVE-2019-15107 漏洞描述 Webmin是一个基于Web的系统配置工具&#xff0c;用于类Unix系统。密码重置页面中存在此漏洞&#xff0c;允许未经身份验证的用户通过简单的 POST 请求执行任意命令。 影响版本 Webmin<1.920 漏洞评级 严重 利用方法&#xff08;利…...

webstorm自定义文件模板(Vue + Scss)

最终效果如下&#xff1a; 具体配置如下&#xff1a; 新增文件代码如下&#xff1a; <!--* Description: ${COMPONENT_NAME} 页面* Author: mhf* Date: ${DATE} --> <template><div>${COMPONENT_NAME} </div> </template><script&g…...

楔子-写在之前

最近一年都在忙着一个项目&#xff0c;并且需要学习另一个领域的知识&#xff0c;从单片机过渡到了LINUX嵌入式&#xff0c;倒静不下心去写点东西。看了下之前写的东西&#xff0c;感觉已经过去了很久很久。现在项目快忙完了&#xff0c;准备把最近的心得给大家分享下。 前言 …...

第 5 章 数组和广义表(稀疏矩阵的三元组顺序表存储实现)

1. 背景说明 为了节省存储空间&#xff0c;可以对这类矩阵进行压缩存储。所谓压缩存储是指&#xff1a;为多个值相同的元只分配一个存储空间&#xff0c;对零元不分配空间。 2. 示例代码 1)status.h /* DataStructure 预定义常量和类型头文件 */ #include <string.h>#i…...

【RabbitMQ 实战】11 队列的结构和惰性队列

一、 队列的结构 队列的组成&#xff1a; 队列由 rabbit_amgqueue_process 和 backing_queue两部分组成。rabbit_amqqueue_process负责协议相关的消息处理&#xff0c;即接收生产者发布的消息、向消费者交付消息、处理消息的确认 (包括生产端的 confirm 和消费端的 ack) 等。…...

Python3-批量重命名指定目录中的一组文件,更改其扩展名

Python3-批量重命名指定目录中的一组文件&#xff0c;更改其扩展名 1.argparse模块2.vars内置函数3.os.listdir(path)4.os.path.splitext(filepath)5.os.path.join6.os.rename7.os.path.isfile8.批量重命名指定目录中的一组文件&#xff0c;更改其扩展名 1.argparse模块 argpa…...

渗透测试KAILI系统的安装环境(第八课)

KAILI系统的安装环境(第八课) Kaili是一款基于PHP7的高性能微服务框架&#xff0c;其核心思想是面向服务的架构&#xff08;SOA&#xff09;&#xff0c;支持http、websocket、tcp等多种通信协议&#xff0c;同时还提供了RPC、Service Mesh、OAuth2等功能。Kaili框架非常适合构…...

如何正确方便的理解双指针?力扣102 (二叉树的层序遍历)

双指针&#xff0c;顾名思义就是指针的指针。 在此之前我们需要先理解单指针 &#xff08;简称为指针&#xff09;。指针很简单&#xff0c;直接上例子&#xff1a;例&#xff1a;现有两个变量&#xff0c;a10,b20. 要求&#xff1a;交换他们的值&#xff0c;输出的结果应为a20…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...