SpringMVC工作原理及源码解析

article/2025/9/14 1:30:09

SpringMVC工作原理及源码解析

  • 一:SpringMVC原理图
  • 二:SpringMVC的主要组件
    • 1、前端控制器DispatcherServlet:
    • 2、处理器映射器HandlerMapping:
    • 3、处理器适配器HandlerAdapter:
    • 4、处理器Handler:
    • 5、控制器Controller:
    • 6、视图解析器ViewResolver:
    • 7、视图View
  • 三:Spring MVC的工作流程
  • 四:Spring 如何保证 Controller 并发的安全?
    • 1、SpringMVC一个Controller处理所有用户请求的并发问题
    • 2、Spring并发访问的线程安全性问题

一:SpringMVC原理图

在这里插入图片描述

二:SpringMVC的主要组件

1、前端控制器DispatcherServlet:

Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。
在这里插入图片描述
我们知道Servlet的service方法是被Servlet容器调用的,这个时机是发生的有客户端向servlet请求服务时调用的,而这些都将其委托给DispatcherServlet的doDispatch方法。我们查看其关键代码。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {//检查请求是否是multipart(即文件上传),若是进行相关处理processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);//通过handermapping映射获取HandlerExecutionChain(处理链中包括了interceptor的前置和后置方法)// Determine handler for the current request.mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}//根据处理器(handler及HandlerExecutionChain)获取处理器适配器(处理器适配器是为了提供统一接口进行后续处理,从而支持多种类型的处理器)// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}//执行chain中拦截器附加的预处理方法,即preHandle方法                  if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}//适配器统一执行handle方法(适配器统一接口的作用),此处是真正处理业务逻辑的地方// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);//执行chain中拦截器附加的后处理方法,即postHandle方法mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException = new NestedServletException("Handler dispatch failed", err);}//处理分发结果:包括解析视图并进行视图渲染,执行chain中拦截器附加的后处理方法,即afterCompletion方法。具体方法内容见下方源码。processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}

2、处理器映射器HandlerMapping:

能够完成客户请求到Controller映射。
在这里插入图片描述
在这里插入图片描述

3、处理器适配器HandlerAdapter:

经过适配调用具体的处理器(Handler,也叫后端控制器),即相应的Controller
将Controller执行结果ModelAndView返回给 DispatcherServlet

4、处理器Handler:

一般来说,Controller是Handler,但Handler不一定是Controller。

例如,HttpRequestHandler,WebRequestHandler,MessageHandler都是可以使用DispatcherServlet的处理程序。 @Controller是执行Web请求并返回视图的处理程序。

简而言之,Handler只是一个术语,它不是一个类或接口。 它可以执行映射。

执行流程都是:
处理映射器通过@Controller注解找到处理器,继而通过@RequestMapping注解找到用户输入的url

5、控制器Controller:

需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个
Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

6、视图解析器ViewResolver:

Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

7、视图View

View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等 等)

三:Spring MVC的工作流程

(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器, 请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦 截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给 DispatcherServlet; (8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行 解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
在这里插入图片描述

DispatcherServlet是整个Spring MVC的核心。它负责接收HTTP请求组织协调Spring MVC的各个组成部分。其主要工作有以下三项:

  1. 截获符合特定格式的URL请求。
  2. 初始化DispatcherServlet上下文对应的WebApplicationContext,并将其与业务层、持久化层的 WebApplicationContext建立关联。
  3. 初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中。

四:Spring 如何保证 Controller 并发的安全?

1、SpringMVC一个Controller处理所有用户请求的并发问题

有状态和无状态的对象基本概念:
有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。一般是prototype scope。

无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。一般是singleton scope。

springMVC中,一般Controller、service、DAO层的scope均是singleton;
每个请求都是单独的线程,即使同时访问同一个Controller对象,因为并没有修改Controller对象,相当于针对Controller对象而言,只是读操作,没有写操作,不需要做同步处理。

Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是 相当于不变(immutable)类,所以不影响。

2、Spring并发访问的线程安全性问题

由于Spring MVC默认是Singleton的,所以会产生一个潜在的安全隐患。根本核心是instance变量保持状态的问题。这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:
一是我们不用每次创建Controller,
二是减少了对象创建和垃圾收集的时间;

由于只有一个Controller的instance,当多个线程同时调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量


http://chatgpt.dhexx.cn/article/HUtgIVJs.shtml

相关文章

SpringMVC工作原理和工作流程

在博客看见一编写的非常清晰的博客,对现在的注重开发层面不注重底层原理的还是有用处的。 原文出处:https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC工作原理 SpringMVC的工作原理图: SpringMVC流程 1、 用户发送请求至前端控制…

SpringMVC的简介概述、工作原理

SpringMVC简述概括 SpringMVC的工作原理

SpringMVC工作原理之参数解析

前面分析到 SpringMVC工作原理之处理映射[HandlerMapping] ,由映射处理器(HandlerMapping) 解析出对应的 handler。接着 SpringMVC工作原理之适配器[HandlerAdapter] 描述了 handler 是怎么匹配到合适的适配器,进行 handler 对应方法的执行。其他几种适配…

16.springmvc工作原理分析

springmvc 如何做URL映射关系 1.SpringIOC容器加载时开始遍历所有的bean对象 判断 bean对象 类上是否有加上 Controller注解,如果类上有加该注解的话 则该类就是为我们控制类; 2.在容器初始化时会建立所有url和controller的对应关系,利用java反射机制…

SpringMVC工作原理及其流程

本文介绍SpringMVC的基本原理,对于一个浏览器请求,SpringMVC的处理流程。 SpringMVC主要包含一下组件 DispatcherServlet-前端控制器HandlerMapping-处理器映射Controller-控制器ViewResolver-视图解析器View-视图Spring的请求流程 SpringMVC的核心在于其请求流程,这是使用…

阿里云YUM源配置

文章目录 阿里云YUM源配置1.备份原有yum源2.根据自己系统下载yum源3.重新加载yum0x00. 阿里云YUM源配置 今天,打开我的Centos7系统,美滋滋要搭建一波LAMP环境。一把梭哈。 yum -y install httpd mariadb mariadb-server php php-mysql 奈何,…

Linux学习-20-yum介绍,yum源配置

7.8 yum介绍,yum源配置 使用 SRPM 源码包和 RPM 二进制包安装软件,这两种方法都比较繁琐,需要手动解决包之间具有依赖性的问题,尤其是库文件依赖,需要自行去 http://www.rpmfind.net 网站上查找相关的 RPM 包。 7.8.…

yum源配置及相关命令

1.yum概述 yum是软件管理仓库,可以完成安装,卸载,自动升级rpm包等任务,能够自动查找并解决rpm包之间的依赖关系,而无需管理员手工安装每个rpm包 2.本地源和网络源 本地源:比如说光盘里面一般会附带一些软件&#xff0c…

redhat yum源配置-已成功

提示:几分钟就搞定,替大家避坑了。 yum源配置 redhat使用yum源时不成功,这是因为使用 redhat 自带的 yum源要付费,所以需要自己重新生成 yum源,Redhat7 和Centos7是完全一样的,可是安装完Redhat7以后&#…

Openstack实验之yum源配置

1.实验目的 对于企业的Openstack私有云,出于对安全和某些因素的安全考虑,有些服务器无法访问公网,导致服务器无法更新某些RPM包,同时内部常有Openstack新特性开发需求,版本的维护与升级,因此非常有必要构建…

CentOS6.5 yum源配置

编辑配置文件 vim /etc/yum.repos.d/CentOS-Base.repo将以下内容复制到配置文件中 [base] nameCentOS-6 failovermethodpriority baseurlhttp://mirrors.aliyun.com/centos-vault/6.5/os/x86_64/ gpgcheck0生成缓存 yum clean all#清除全部 yum makecache#生成缓存也可以 c…

阿里云的yum源配置

首先,将目录切换至/etc/yum.repos.d,这个是需要更换的yum源,一般系统都自带有yum源,但是下载速度很慢,所以需要将yum源换为国内的yum源, 这里一般有两种方法: 1、首先使用wget 下载阿里云的yum源…

FTP - YUM 源配置

** Ftp yum源配置 一、 环境需要 1、2台centos A和B 2、配置两台主机的ip 3、关闭防火墙(2台) [rootlocalhost ~]# systemctl stop firewalld[rootlocalhost ~]# systemctl disable firewalld关闭selinux [rootlocalhost ~]# vim /etc/sysconfig/selinux把SELINUXenforcing改…

yum源配置,这一篇就够了!(包括本地,网络,本地共享yum源)

服务器yum源配置 文章目录 1. 引言1.1 什么是yum源1.2 为什么要搭建内网yum源1.3 准备工作 2. yum源搭建2.1 网络yum源配置2.1.1 yum仓库配置2.1.2 更新yum源2.1.3centos yum源一键配置命令2.1.4 其他yum源参考 2.2 本机单机yum源配置2.2.1 iso镜像获取并上传到服务器2.2.2 rep…

Linux下局域网yum源配置

文章目录 一 需求二 搭建环境准备三 服务端1 创建镜像存放目录与挂载目录2 上传centos7镜像3 对镜像文件进行挂载4 配置本地yum源5 对挂载点建立软链接6 安装http服务7 浏览器验证http服务是否正常启动 四 客户端1 修改yum配置文件2 查看yum源 一 需求 企业内部服务器出于安全…

yum源配置教程

环境:Centos7系统、Centos7镜像文件(下文中提到的光盘)、能连接互联网 yum是Linux平台下的一个包管理工具,全称叫做Yellow dog Updater,Modified,Shell前端软件包管理器。基于RPM包管理,能够从指定的服务器…

本地Yum源配置

Yum源访问方式有三种,分别是互联网yum源、局域网yum源、本地yum源 yum可以自动处理依赖关系,并且一次安装所有依赖包,无须繁琐地一次次下载、安装。 配置本地yum源之前需要通过Xftp连接上传操作系统的CentOS-7-x86_64-DVD-2009.iso镜像文件…

Yum源配置

一、使用网络yum源 1、百度搜索网易mirror; 2、找到Centos帮助文档; 3、备份默认yum源; 4、复制repo文件源地址; 5、Centos中使用wget命令下载repo文件; 6、清除yum源缓存; # yum clean all 7、生成新的y…

yum 源配置

CentOS6国内常用yum源站点 原创 WalkingCloud212022-03-01 16:16:46©著作权 文章标签centossed缓存文章分类其它其它阅读数709 ​1、腾讯云镜像站​ ​ ​ ​​ ​​ ​1)替换之前先备份旧配置​ ​mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Ba…

如何配置YUM源

如何配置YUM源 一、YUM简介二、YUM源的配置与更新 一、YUM简介 YUM(yellowdong updater modified)是一个功能完善、易于使用的软件维护工具,它可以根据用户的要求分析出所需软件包及其相关的依赖关系,然后自动从服务器&#xff0…