🎄SpringMVC的执行流程
🍭概述
先用一句话概括 SpringMVC就是Servlet的强大的实现的封装✨
在JavaWeb的开发中 其实单单使用Servlet理论上就可以解决所有的问题(获取请求的数据和页面、渲染后返回给客户端) 只不过实现过程是使用原始的API 所以会更费力 工作量更大 SpringMVC也需要做这些事情 但是它让之前的繁琐工作得以简化
SpringMVC做的事情就是把一些通用的底层代码🧱封装起来 同时提供一些好用的注解 把底层代码隐藏起来 只面向更高层的接口进行开发 从而提升开发效率
在SpringMVC中 最核心的一个类就是🎯
DispatchServlet
其实它就是一个Servlet的实现类 拥有强大的功能 可以将它称为中央分发控制器 它参与了整个后端响应客户端请求的过程 下图的SpringMVC的执行流程可见DispatchServlet
在SpringMVC的执行流程中所担当的核心角色
从图中我们可以看到 SpringMVC做的事情的⚡流程:
- 先获取处理器执行链 这个执行链其实就是客户端的请求需要经过多少次处理 把这些处理以一个链的形式返回给
DispatchServlet
然后DispatchServlet
根据这个执行链去调用其他的Servlet来执行处理- 获取到处理器执行链之后
DispatchServlet
依次获取处理器适配器 根据适配器找到对应的处理器(就是一个Servlet)来进行处理 并获取返回结果ModelAndView对象 这个对象就是获取的数据- 获取到数据以后 还需要获取页面 所以接来下会调用ViewResolver对象获取页面
- 得到页面以后 把之前获取的到的数据填充到页面 并对页面进行渲染
- 最后 返回给客户端结果页面
📑总结来说 就是获取数据 + 页面 -> 进行渲染 -> 返回页面(当然 如果请求只需获取数据 那么只需要返回JSON数据就可以了 在Ajax请求中一般要返回JSON数据而不是页面)
🍭源码Debug准备
光有上面的理论是不够的 接下来对源码进行⚡Debug以让理论得到验证
这个验证将会在
SpringBoot
项目下进行 前提是在Application.yml
文件中设置Thymeleaf
模板引擎
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html # 模板文件名后缀
encoding: UTF-8
content-type: text/html
mode: HTML
web开发依赖
<!-- 导入和web开发相关的所有依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
⚡创建DebugController类
在SpringBoot项目中创建一个新的
DebugController
代码如下
package com.xmall.controller;
/**
@author Liu Xianmeng
@createTime 2023/10/13 16:13
@instruction 用于Debug测试 SpringMVC的执行流程
*/
@SuppressWarnings({"all"})
@Controller
public class DebugController {
@RequestMapping("/debug/getModelAndView")
public ModelAndView getModelAndView(HttpServletRequest request, HttpServletResponse response) {
// 创建一个新的ModelANDView对象
ModelAndView modelAndView = new ModelAndView();
// 设置视图的名字 这个result.html页面等会就会创建
modelAndView.setViewName("result");
// 为modelAndView对象添加一个数据
modelAndView.addObject("name", "BigBigMeng");
// 返回modelAndView对象 -> 给客户端(浏览器)
return modelAndView;
}
}
⚡创建result.html页面
注意这个页面要放在
Application.yml
配置的前缀prefix:classpath:/templates/
目录下
<!DOCTYPE html>
<!-- 使用Thymeleaf模板引擎 -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>result页面</title>
</head>
<body>
<h1>result页面</h1>
<h2>返回的model信息:<span th:text="${name}"></span></h2>
</body>
</html>
⚡启动项目·执行测试
启动项目
执行测试
🍭源码Debug实战
⚡预备动作
1️⃣首先 全局查找
DispatcherServlet
类 找到它的doService
方法 并打上断点 启动项目
2️⃣浏览器访问
3️⃣查看后端
4️⃣继续添加断点 并放行
5️⃣放行后 看到设置的上下文是一个函数
getWebApplicationContext()
的返回结果
6️⃣对这个函数进行估值
⚡执行分发操作
7️⃣下一个断点 ->
doDispatch
执行分发Servelet
⚡获取到处理器执行链和handlerMapping
8️⃣进入
doDispatch
方法
⚡获取到handlerAdapter
⚡执行handler方法
9️⃣用反射调用目标方法 进入
ha.handle
方法
🔟进入
handleInternal
方法
1️⃣1️⃣进入
invokeHandlerMethod
方法
1️⃣2️⃣放行
断点回到DebugController类:
1️⃣3️⃣得到ModelAndView对象
⚡返回ModelAndView对象
1️⃣4️⃣继续放行
⚡对页面进行渲染
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
...
View view;
String viewName = mv.getViewName();
if (viewName != null) {
// We need to resolve the view name.
// ⚡⚡⚡执行视图解析
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
...
}
⚡执行视图解析
⚡最后一步 视图渲染
⚡返回页面结果
🍭总结
到此 SpringMVC的执行流程就分析完毕啦~