谈谈SpringMVC底层原理

一、什么是SpringMVC

之前一直觉得会使用框架就懂了,但其实底层原理我们也要清楚,这样使用的时候就会更加有逻辑,而不是只停留在表面

SpringMVC是Spring生态体系内置的MVC分层Web请求处理框架 ,底层基于原生Servlet规范实现,核心入口为DispatcherServlet中央调度器。 它专门用于服务端接收HTTP请求、参数绑定、调用业务层、封装返回结果,是传统SSM框架、现代SpringBoot后端接口开发的Web底层支撑,所有SpringBoot Web接口本质底层都在运行SpringMVC。

MVC三层拆分含义:

  1. Model(模型):封装业务数据、数据库查询结果,对应项目中的Service、DAO、实体类;
  2. View(视图):页面展示层,如JSP、Thymeleaf、HTML模板;前后端分离项目几乎舍弃视图层,统一返回JSON;
  3. Controller(控制器) :接收前端请求,协调Model与View,处理请求分发逻辑,开发者编写的@RestController/@Controller即为控制器。

二、SpringMVC核心特点与优势

1. 基于注解开发,无强制类继承约束

原生Servlet开发必须继承HttpServlet重写doGet/doPost方法,耦合度极高; SpringMVC仅通过@Controller@RestController标记普通POJO类即可作为控制器,无需继承任何框架类、实现接口,代码轻量化、低耦合。

2. 分层解耦,职责单一

整套框架拆分多个独立组件:调度器、处理器映射器、处理器适配器、视图解析器,每个组件只负责一件事,符合单一职责原则,组件可灵活替换扩展。

3. 原生支持RESTful接口规范

提供@GetMapping@PostMapping@PutMapping@DeleteMapping系列注解,天然支持REST风格接口设计,搭配@RestController快速实现前后端分离JSON返回。

4. 内置拦截器机制,统一请求增强

提供HandlerInterceptor拦截器,可在Controller执行前后、请求结束后自定义逻辑,用于登录校验、权限拦截、日志记录,区别于Servlet过滤器Filter,仅作用于SpringMVC内部请求。

5. 强大的参数自动绑定与类型转换

前端表单、URL路径参数、JSON请求体,框架自动封装到实体类,自动完成字符串、数字、日期等类型转换,无需手动通过request.getParameter()取值。

6. 容器统一管理,依托Spring IOC

所有Controller、拦截器、工具组件都交由Spring IOC容器管理,自动实现依赖注入,Controller可直接注入Service、Mapper,无需手动创建对象。

7. 灵活的视图解析机制

内置InternalResourceViewResolver视图解析器,自动拼接页面前缀后缀,传统服务端渲染项目可快速跳转页面;前后端分离场景直接跳过视图解析,序列化对象返回JSON。

三、核心组件对应图讲解(结合流程图)

图片来源于网络

先梳理图中全部核心组件,明确每个组件定位:

  1. DispatcherServlet(中央调度器) :SpringMVC总入口,所有HTTP请求第一道关口,全局总指挥;本质是HttpServlet子类,底层依托Servlet运行。
  2. HandlerMapping 处理器映射器:只做查询工作,根据请求URL匹配对应Controller方法,封装成处理器执行链返回。
  3. HandlerExecutionChain 处理器执行链:封装目标Handler(Controller方法)+ 全部拦截器集合,类比过滤器链。
  4. HandlerAdapter 处理器适配器:统一执行规范,适配不同类型Controller,真正调用Controller业务方法。
  5. Handler(Controller) 处理器:开发者编写的接口业务类,调用Service操作数据库。
  6. ModelAndView:封装Controller返回的数据(Model)与视图名称(View),前后端分离项目不会生成该对象。
  7. ViewResolver 视图解析器:拼接页面路径,定位前端视图文件。
  8. View 视图:页面模板,渲染数据并生成最终页面返回浏览器。

四、基于流程图的完整11步执行流程

步骤1:浏览器发起HTTP请求

前端通过URL发送GET/POST/PUT/DELETE请求,请求抵达服务端,首先进入DispatcherServlet中央调度器。

补充:SSM需要在web.xml手动注册DispatcherServlet;SpringBoot通过自动配置WebMvcAutoConfiguration自动创建注册,无需XML配置。

步骤2:DispatcherServlet调用HandlerMapping处理器映射器

调度器将当前请求交给HandlerMapping,核心作用:解析当前请求URL,扫描项目中所有Controller,匹配该URL对应的目标业务方法。

步骤3:HandlerMapping返回HandlerExecutionChain执行链

匹配完成后,映射器返回一条执行链,包含两部分:

  1. Handler:目标Controller方法;
  2. 拦截器数组:当前请求需要执行的所有Interceptor拦截器。

步骤4:DispatcherServlet调用HandlerAdapter处理器适配器

调度器拿到执行链后,不直接执行Controller,交给适配器。 设计适配器的原因:SpringMVC支持多种类型控制器(注解Controller、传统Controller),适配器统一封装调用逻辑,调度器无需关心Controller底层实现。

步骤5:HandlerAdapter调用目标Handler(Controller)

适配器按照统一反射逻辑,执行匹配到的Controller接口方法,自动完成请求参数封装、类型转换。

步骤6:Controller调用Service、DAO操作数据库

控制器执行业务逻辑,调用Service层处理业务,DAO层查询/修改数据库,拿到业务结果数据。

步骤7:Controller返回ModelAndView对象

  1. 传统服务端渲染(JSP/Thymeleaf) :方法返回数据+视图名称,封装为ModelAndView;Model存放页面所需数据,View代表页面文件名。
  2. 前后端分离项目(@RestController) :方法添加@ResponseBody,直接返回实体对象、字符串,框架使用Jackson自动序列化为JSON,不会生成ModelAndView,直接跳过视图解析流程

步骤8:DispatcherServlet调用ViewResolver视图解析器

仅传统页面项目会执行此步骤;调度器将ModelAndView交给视图解析器,自动拼接页面前缀、后缀,找到服务器存放的真实视图文件。 例:视图名为user,前缀/templates/,后缀.html,最终定位/templates/user.html

步骤9:视图解析器返回View视图对象

解析完成后,返回封装好路径的视图对象。

步骤10:View执行视图渲染

框架将Model中存储的业务数据填充到HTML/JSP页面,完成页面渲染,生成完整静态页面。

步骤11:DispatcherServlet向前端返回HTTP响应

  1. 页面项目:将渲染完成的HTML页面作为响应返回浏览器;
  2. 前后端分离项目:直接返回JSON字符串,无视图渲染步骤。

五、流程关键补充知识点(面试高频拓展)

1. 拦截器Interceptor执行时机(内嵌在执行链中)

一条完整请求中拦截器执行顺序:

  1. preHandle:Controller执行前,返回false直接拦截请求,流程终止;
  2. postHandle:Controller执行完毕,视图渲染之前;
  3. afterCompletion:整个请求全部结束,资源释放、日志记录。

拦截器属于SpringMVC自有组件,仅DispatcherServlet内部生效;Filter过滤器属于Servlet原生规范,先执行Filter,再进入DispatcherServlet,最后执行拦截器

2. HandlerMapping与HandlerAdapter的分工区别

  • HandlerMapping:只负责查找,根据URL找到Controller,不执行任何业务代码;
  • HandlerAdapter:只负责执行,统一调用Controller方法,不做匹配查找。

3. @Controller 和 @RestController 对流程的影响

  1. @Controller:无自动JSON转换,方法返回字符串会进入视图解析流程,跳转页面;如需返回JSON,方法上加@ResponseBody
  2. @RestController = @Controller + @ResponseBody:类内所有方法自动序列化对象为JSON,直接跳过步骤8、9、10,不执行视图渲染,适配前后端分离开发。

4. url-pattern / 和 /* 的区别

SSM配置DispatcherServlet拦截路径:

  1. /:拦截所有普通HTTP请求,不拦截.jsp页面,是标准配置;
  2. /*:拦截包含JSP在内的全部请求,会导致页面被控制器拦截,页面404,禁止使用。

5. Spring两级容器关系

Spring存在父子容器:

  1. 父容器(根容器):管理Service、Mapper、工具Bean;
  2. DispatcherServlet子容器:管理Controller、拦截器; 子容器可获取父容器所有Bean,父容器无法访问子容器Bean;SpringBoot自动整合两级容器,无需手动配置。

六、总结

SpringMVC依托Servlet实现,以DispatcherServlet为调度核心,通过分层组件拆分请求处理全流程,实现了请求分发、参数绑定、业务调用、视图渲染完整能力。 对比原生Servlet,它依托注解简化开发、分层解耦、支持REST接口;如今SpringBoot虽大幅简化配置,但Web开发底层依旧完全依赖SpringMVC整套执行逻辑。

相关推荐
夕除19 小时前
请求区别及app网站区别
后端
w1395485642219 小时前
鸿蒙原生开发手记:徒步迹 - 图片加载与缓存优化
后端
程序员爱钓鱼20 小时前
Rust 数组 Array 详解:定义、访问、遍历与切片
后端·rust
前端工作日常1 天前
我学习到的Java类和对象区别
java·后端
前端工作日常1 天前
我学习到的Java类完整结构
java·后端
Csvn1 天前
📊 SQL 入门 Day 6:多表查询 — JOIN 的四种姿势
后端·sql
hold?fish:palm1 天前
RDB全量快照备份
c++·redis·后端
LucianaiB1 天前
我把刘备一生做成了可播放的高德地图,还把整套方法封装成了 Skill
后端
Reart1 天前
操作系统实验哈工大lab2——系统调用
后端·操作系统