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

【Spring MVC】DispatcherServlet 请求处理流程

一、 请求处理

Spring MVC 是 Spring 框架的一部分,用于构建 Web 应用程序。它遵循 MVC(Model-View-Controller)设计模式,将应用程序分为模型(Model)、**视图(View)控制器(Controller)**三个部分。

DispatcherServlet 处理流程:

在这里插入图片描述

  1. 当用户发起请求时,会将请求直接传入前端控制器 DispatcherServlet ,它是 Spring MVC 核心组件,负责接收请求并分发到各自的处理器中
  2. DispatcherServlet 接收到请求后,会调用 HandlerMapping 组件。HandlerMapping 根据请求的 URL 查找合适的处理器(Handler)。这里的 Handler 通常是指 Controller 中的方法,这些方法通常带有 @RequestMapping 注解(或其变体如 @GetMapping , @PostMapping 等)。
  3. DispatcherServlet 获取到合适的 Handler 后,会调用 HandlerAdapter 组件。HandlerAdapter 负责执行处理器方法,并处理方法的返回值。HandlerAdapter同样会去 Handler (Controller)中找那些带有 @RequestMapping 注解的方法
  4. HandlerAdapter 调用 Controller 中的方法,执行业务逻辑。处理完业务后,会返回一个 ModelAndView 对象给 HandlerAdapter。ModelAndView 对象中包含模型数据(Model)和视图名称(View)。
  5. DispatcherServlet 从 HandlerAdapter 获取到 ModelAndView 对象后,会调用 ViewResolver 组件。ViewResolver 负责将视图名称解析为实际的视图对象。
  6. DispatcherServlet 获取到具体的视图对象后,将模型数据传递给视图对象View进行渲染。
  7. 渲染完成后,DispatcherServlet 将生成的响应内容返回给用户,浏览器显示最终的页面。

在这里插入图片描述

  1. 客户端发出请求,会先经过 filter 过滤,通过的请求才能到达 DispatcherServlet。
  2. DispatcherServlet 通过 handlerMapping 找到请求对应的 handler,返回一个 HandlerExecutionChain 里面包含 interceptors 和 handler
  3. DispatcherServlet 通过 handlerAdapter 调用实际的 handler 处理业务逻辑, 返回 ModelAndView。里面会包含逻辑视图名和 model 数据。注意,在此之前和之后,会分别调用 interceptors 拦截处理
  4. 调用 viewResolver 将逻辑视图名解析成 view 返回
  5. 调用 view.render 渲染视图,写进 response。然后 interceptors 和 filter 依次拦截处理,最后返回给客户端

HandlerInterceptor

拦截器。在 handler 执行前后及视图渲染后执行拦截,可以注册不同的 interceptor 定制工作流程

public interface HandlerInterceptor {// 在 handler 执行前拦截,返回 true 才能继续调用下一个 interceptor 或者 handlerdefault boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}// 在 handler 执行后,视图渲染前进行拦截处理default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception {}// 视图渲染后,请求完成后进行处理,可以用来清理资源// 除非 preHandle 放回 false,否则一定会执行,即使发生错误default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {}}

二、设计原理

Servlet 规范

SpringMVC 是基于 Servlet 的。

Servlet 是运行在 web 服务器上的程序,它接收并响应来自 web 客户端的请求(通常是 HTTP 请求)。

Servlet 规范有三个主要的技术点: Servlet, Filter, Listener

1. Servlet

Servlet 是实现 Servlet 接口的程序。对于 HTTP, 通常继承 javax.servlet.http.HttpServlet, 可以为不同的 URL 配置不同的 Servlet。Servlet 是"单例"的,所有请求共用一个 Servlet, 因此对于共享变量(比如实例变量),需要自己保证其线程安全性。DispatcherServlet 便是一个 Servlet。

Servlet 生命周期

  1. Servlet 实例化后,Servlet 容器会调用 init 方法初始化。init 只会被调用一次,且必须成功执行才能提供服务。
  2. 客户端每次发出请求,Servlet 容器调用 service 方法处理请求。
  3. Servlet 被销毁前,Servlet 容器调用 destroy 方法。通常用来清理资源,比如内存,文件,线程等。
2. Filter

Filter 是过滤器,用于在客户端的请求访问后端资源之前,拦截这些请求;或者在服务器的响应发送回客户端之前,处理这些响应。只有通过 Filter 的请求才能被 Servlet 处理。

Filter 可以通过配置(xml 或 java-based)拦截特定的请求,在 Servlet 执行前后(由 chain.doFilter 划分)处理特定的逻辑,如权限过滤,字符编码,日志打印,Session 处理,图片转换等

Filter 生命周期

  1. Filter 实例化后,Servlet 容器会调用 init 方法初始化。init 方法只会被调用一次,且成功执行(不抛出错误且没有超时)才能提供过滤功能

  2. 客户端每次发出请求,Servlet 容器调用 doFilter 方法拦截请求。

    public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {// 客户端的请求访问后端资源之前的处理逻辑System.out.println("我在 Servlet 前执行");// 把请求传回过滤链,即传给下一个 Filter, 或者交给 Servlet 处理chain.doFilter(request,response);// 服务器的响应发送回客户端之前的处理逻辑System.out.println("我在 Servlet 后执行");
    }
    
  3. Filter 生命周期结束时调用 destroy 方法,通常用来清理它所持有的资源,比如内存,文件,线程等。

3. Listener

Listener 是监听某个对象的状态变化的组件,是一种观察者模式。

被监听的对象可以是域对象 ServletContext, Session, Request

监听的内容可以是域对象的创建与销毁,域对象属性的变化

ServletContextHttpSessionServletRequest
对象的创建与销毁ServletContextListenerHttpSessionListenerServletRequestListener
对象的属性的变化ServletContextAttributeListenerHttpSessionAttributeListenerServletRequestAttributeListener

WebApplicationContext

SpringMVC 用 Spring 化的方式来管理 web 请求中的各种对象。

什么是 Spring 化? IOC 和 AOP, 这不是本文的重点,具体自行查阅。

SpringMVC 会通过 WebApplicationContext 来管理服务器请求中涉及到的各种对象和他们之间的依赖关系。

WebApplicationContext 继承自 ApplicationContext, 它定义了一些新的作用域,提供了 getServletContext 接口。

public interface WebApplicationContext extends ApplicationContext {// 根容器名,作为 key 存储在 ServletContext 中; ServletContext 持有的 WebApplicationContextString ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";/*** 这三个是 WebApplicationContext 特有的作用域* 通过 WebApplicationContextUtils.registerWebApplicationScopes 注册相应的处理器*/String SCOPE_REQUEST = "request";String SCOPE_SESSION = "session";String SCOPE_APPLICATION = "application";/*** ServletContext 在 WebApplicationContext 中的名字* 通过 WebApplicationContextUtils.registerEnvironmentBeans 注册到 WebApplicationContext 中*/String SERVLET_CONTEXT_BEAN_NAME = "servletContext";/*** ServletContext 和 ServletConfig 配置参数在 WebApplicationContext 中的名字* ServletConfig 的参数具有更高的优先级,会覆盖掉 ServletContext 中的参数* 值为 Map<String, String> 结构*/String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";/*** ServletContext 属性信息在 WebApplicationContext 中的名字* 值为 Map<String, String> 结构* 属性是用来描述 ServletContext 本身的一些信息的*/String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";/*** 获取 ServletContext 接口*/@NullableServletContext getServletContext();}
WebApplicationContext 类图

img

ApplicationContext 有一个抽象实现类 AbstractApplicationContext, 模板方法的设计模式。它有一个 refresh 方法,它定义了加载或初始化 bean 配置的基本流程。后面的实现类提供了不同的读取配置的方式,可以是 xml, annotation, web 等,并且可以通过模板方法定制自己的需求。

AbstractApplicationContext 有两个实现体系, 他们的区别是每次 refresh 时是否会创建一个新的 DefaultListableBeanFactory。DefaultListableBeanFactory 是实际存放 bean 的容器, 提供 bean 注册功能。

  1. AbstractRefreshableApplicationContext 这个 refreshable 并不是指 refresh 这个方法,而是指 refreshBeanFactory 这个方法。他会在每次 refresh 时创建一个新的 BeanFactory(DefaultListableBeanFactory)用于存放 bean,然后调用 loadBeanDefinitions 将 bean 加载到新创建的 BeanFactory。
  2. GenericApplicationContext 内部持有一个 DefaultListableBeanFactory, 所以可以提前将 Bean 加载到 DefaultListableBeanFactory, 它也有 refreshBeanFactory 方法,但是这个方法啥也不做。

根据读取配置的方式,可以分成 3 类,基于 xml 的配置, 基于 annotation 的配置基于 java-based 的配置

  1. 基于 xml 的配置使用 xml 作为配置方式, 此类的名字都含有 Xml, 比如从文件系统路径读取配置的 FilePathXmlApplicationContext, 从 ClassPath 读取配置的 ClassPathXmlApplicationContext, 基于 Web 的 XmlWebApplicationContext 等
  2. 基于注解的配置通过扫描指定包下面具有某个注解的类,将其注册到 bean 容器,相关注解有 @Component, @Service, @Controller, @Repository,@Named 等
  3. java-based 的配置方式目前是大势所趋,结合注解的方式使用简单方便易懂,主要是 @Configuration 和 @Bean

上面几个类是基础类,下面是 SpringMVC 相关的 WebApplicationContext

  1. XmlWebApplicationContext 和 AnnotationConfigWebApplicationContext 继承自 AbstractRefreshableApplicationContext,表示它们会在 refresh 时新创建一个 DefaultListableBeanFactory, 然后 loadBeanDefinitions。 它们分别从 xml 和 注解类(通常是 @Configuration 注解的配置类)中读取配置信息。

  2. XmlEmbeddedWebApplicationContext 和 AnnotationConfigEmbeddedWebApplicationContext 继承自 GenericApplicationContext,表示他们内部持有一个 DefaultListableBeanFactory, 从名字可以看出它们是用于 “Embedded” 方面的,即 SpringBoot 嵌入容器所使用的 WebApplicationContext

  3. SpringMVC 应用中几乎所有的类都交由 WebApplicationContext 管理,包括业务方面的 @Controller, @Service, @Repository 注解的类, ServletContext, 文件处理 multipartResolver, 视图解析器 ViewResolver, 处理器映射器 HandleMapping 等。

相关文章:

【Spring MVC】DispatcherServlet 请求处理流程

一、 请求处理 Spring MVC 是 Spring 框架的一部分&#xff0c;用于构建 Web 应用程序。它遵循 MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;将应用程序分为模型&#xff08;Model&#xff09;、**视图&#xff08;View&#xff09;和控制器&#x…...

【优选算法】——二分查找!

目录 1、二分查找 2、在排序数组中查找元素的第一个和最后一个位置 3、搜索插入位置 4、x的平方根 5、山脉数组的封顶索引 6、寻找峰值 7、寻找旋转排序数组中的最小值 8、点名 9、完结散花 1、二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组…...

leetcode hot100【LeetCode 300. 最长递增子序列】java实现

LeetCode 300. 最长递增子序列 题目描述 给定一个未排序的整数数组 nums&#xff0c;找出其中最长递增子序列的长度。 要求&#xff1a; 子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0…...

sql注入——靶场Less1

?id1 ?id99union select 1,2,3-- 查看占位 ?id1 order by 3-- 尝试出表有几列 ?id1 order by 4-- 说明只有三列 ?id99 union select 1,database(),3-- 查询当前使用的数据库的名称 ?id99 union select 1,group_concat(table_name),3 from information_schema.tables …...

docker file容器化部署Jenkins(一)

Jenkins Github地址&#xff1a;https://github.com/jenkinsci/jenkins 国内镜像地址&#xff1a;https://docker.aityp.com/ 准备工作 # 创建持久化卷目录 mkdir /data/jenkins_home/Jenkins拉取镜像 # 由于Jenkins需要JDK&#xff0c;所以直接拉取带有JDK的Jenkins镜像 doc…...

ArkTS组件继承的高级用法

在HarmonyOS应用开发中&#xff0c;ArkTS作为开发语言&#xff0c;组件的继承是实现代码复用和扩展功能的重要机制。本文将详细介绍ArkTS中组件继承的高级用法&#xff0c;包括继承的概念、如何使用继承、以及继承在实际开发中的应用和最佳实践。 继承的概念 继承是面向对象编…...

第十二章 spring Boot+shiro权限管理

学习目标 引入依赖配置Shiro设计数据库表编写Mapper、Service和Controller前端页面测试与调优其他注意事项 Spring Boot与Shiro的集成是一种常见的Java Web应用程序权限管理解决方案。Shiro是一个强大的Java安全框架&#xff0c;提供了认证、授权、会话管理、加密等安全功能。以…...

jmeter基础01-3_环境准备-Linux系统安装jdk

Step1. 查看系统类型 打开终端&#xff0c;命令行输入uname -a&#xff0c;显示所有系统信息&#xff0c;包括内核名称、主机名、内核版本等。 如果输出是x86_64&#xff0c;则系统为64位。如果输出是i686 或i386&#xff0c;则系统为32位。 Step2. 官网下载安装包 https://www…...

数字证书的简单记录

CA&#xff08;Certificate Authority&#xff09;&#xff1a;即数字证书颁发认证机构。 CA数字证书&#xff08;crt/cer证书&#xff09;&#xff1a;数字证书 申请者与颁发者信息申请者公钥颁发者签名&#xff0c;由CA机构使用私钥签名得到数字证书。 CA中间证书&#xff1…...

ssm基于SSM的校内信息服务发布系统的设计与实现+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 摘要 1 Abstract 1 目 录 2 1绪论 4 1.1研究背景与意义 4 1.2国内外研究现状 4 1.3研究…...

Java 教程简介

Java 教程简介 Java 是 Sun Microsystems 公司于 1995 年 5 月推出的一种面向对象的编程语言和运行平台&#xff0c;由 James Gosling 和他的同事共同研发。当前&#xff0c;这个产品已被 Oracle 公司所收购。这篇教程将带你了解 Java 的一些基础知识和应用。 Java 系统简介 …...

【C/C++】【三种方法】模拟实现strlen

学习目标&#xff1a; 使用代码模拟实现strlen。 逻辑&#xff1a; strlen 需要输入一个字符串数组类型的变量&#xff0c;并且返回一个整型类型的数据。strlen 需要计算字符串数组有多少个元素。 代码1&#xff1a;使用计数器 #define _CRT_SECURE_NO_WARNINGS 1 #include&…...

外贸平台开发多语言处理的三种方式

随着全球贸易的不断增长&#xff0c;外贸平台的多语言处理已成为提升用户体验和市场竞争力的重要因素。在开发外贸平台时&#xff0c;有多种方法可以实现多语言支持。本文将探讨三种主要的多语言处理方式&#xff1a;数据库级多语言支持、前端国际化框架以及内容管理系统&#…...

学习GCC

浅显易懂的GCC使用教程——初级篇_gcc -ddebug-CSDN博客 本文摘抄学习自上面的文章&#xff01; GCC: GNU Compiler Collection: GNU编译器套件&#xff0c;属于一种编程语言编译器&#xff0c;其原名为GCC(GNU C Compiler)&#xff0c;即GNU c语言编译器&#xff0c;虽然缩写…...

B2109 统计数字字符个数

B2109 统计数字字符个数 #include <iostream> using namespace std; # include <string.h> #include <ctype.h> #include <algorithm> int main(){ char str[256]; cin.getline(str,256); //fgets(str,256,stdin); int cnt 0; //for(size_t i 0…...

springboot Lark扫码登录

登录流程 测试通过的地址&#xff1a; https://open.larksuite.com/open-apis/authen/v1/index?app_idcli_a7add3c5bb38902f&redirect_urihttp%3A%2F%2Fstrongculture.cn&stateSTATE...

中专女生数赛疑云:阿里蒙冤,学校之过,尽显世态炎凉

11月3日&#xff0c;阿里巴巴全球数学竞赛组委会发布2024阿里巴巴全球数学竞赛有关情况说明&#xff1a;在本届竞赛中&#xff0c;江苏省涟水中等专业学校教师王某某和其指导的学生入围决赛&#xff0c;引发社会关注。根据决赛阅卷结果&#xff0c;二人未获奖。据调查了解&…...

【neo4j】 图数据库neo4j cypher单一语句 optional 可选操作的技巧

neo4j cypher单一语句 optional 可选操作的技巧 参考文章&#xff1a; Optional merge on relationships Cyper Merge on Optional Match 背景&#xff1a; 使用 match some node 中间还有一些可能与此node有联系的关系或者节点需要处理 create/merge/delete MATCH (src:SOU…...

ip地址分为几大类-IP和子网掩码对照表

一、IP地址的基本概念与分类 IP地址是用于在网络中标识每个设备的逻辑地址。互联网协议将IP地址分为A、B、C、D和E五类&#xff0c;其中A、B、C三类最常用&#xff0c;它们主要根据地址的首位位数以及用途进行划分。 A类地址&#xff1a; 范围&#xff1a;0.0.0.0 - 127.255.2…...

第四篇: 用Python和SQL在BigQuery中进行基础数据查询

用Python和SQL在BigQuery中进行基础数据查询 在大数据分析领域&#xff0c;Google BigQuery 提供了一种快速且经济高效的数据处理方式。对于想要使用SQL查询大规模数据的读者来说&#xff0c;BigQuery的公共数据集资源丰富、操作简便&#xff0c;是学习和实践SQL基础操作的理想…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...