2022尚硅谷SSM框架跟学 九 Spring MVC基础四
14.SpringMVC执行流程
14.1SpringMVC常用组件
- DispatcherServlet:前端控制器,不需要工程师开发,由框架提供。
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求。 - HandlerMapping:处理器映射器,不需要工程师开发,由框架提供。作用:根据请求的url、method等信息查找Handler,即控制器方法。
- Handler:处理器,需要工程师开发。
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 - HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供
作用:通过HandlerAdapter对处理器(控制器方法)进行执行。 - ViewResolver:视图解析器,不需要工程师开发,由框架提供。
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、RedirectView。 - View:视图
作用:将模型数据通过页面展示给用户
14.2DispatcherServlet初始化过程(Init)
DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet生命周期来进行调度。
先看一下类图的继承关系
public interface Servlet
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
public abstract class HttpServlet extends GenericServlet
没有重写
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware
之后开始初始化
(1).初始化WebApplicationContext
所在类:org.springframework.web.servlet.FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
点进去initWebApplicationContext方法继续看源码
之后创建WebApplicationContext
(2).创建WebApplicationContext
所在类:org.springframework.web.servlet.FrameworkServlet
点进去createWebApplicationContext方法继续看
点进去看createWebApplicationContext有参方法
继续看FrameworkServlet.class的WebApplicationContext方法
我们点进去看onRefresh
public class DispatcherServlet extends FrameworkServlet
(3).DispatcherServlet初始化策略
FrameworkServlet创建WebApplicationContext后,刷新容器,调用onRefresh(wac),此方法在DispatcherServlet中进行了重写,调用了initStrategies(context)方法,初始化策略,即初始化DispatcherServlet的各个组件。
所在类:org.springframework.web.servlet.DispatcherServlet
点进去initStrategies方法
14.3DispatcherServlet调用组件处理请求(Service)
从顶层接口开始看
public interface Servlet
实现类
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
public abstract class HttpServlet extends GenericServlet
发现有2个service方法
先看重写父类的
再看HttpServlet.class自己重载的
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
没有重写service方法
(1).processRequest()
FrameworkServlet重写HttpServlet中的service()和doXxx(),这些方法中调用了processRequest(request, response)
所在类:org.springframework.web.servlet.FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
这里的父类指的是HttpServlet.class中的service
而我们看子类FrameworkServlet.class,重写了4种请求
发现4种请求方式调用的方法都是processRequest
那我们来看一下processRequest方法
发现核心方法是doService,而doService是一个抽象方法,需要子类继承
(2).doService()
所在类:org.springframework.web.servlet.DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
方法比较长我们直接看核心方法doDispatch来处理请求
(3).doDispatch()
所在类:org.springframework.web.servlet.DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
方法比较长,我们往下看,看到了之前熟悉的代码
我们继续看processDispatchResult
(4).processDispatchResult()
所在类:org.springframework.web.servlet.DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
往下拉,下面也有拦截器
看render方法渲染视图
14.4SpringMVC的执行流程
(1).用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。
(2).DispatcherServlet对请求URL(统一资源定位符,带协议、IP地址、端口号;理解为资源在网络中的路径)进行解析,得到请求资源标识符(URI,不带协议、不带IP地址、不带端口号;理解为资源在服务器中的路径),判断请求URI对应的映射:
(a).不存在
i.再判断是否配置了mvc:default-servlet-handler(默认的servlet,可以加载静态页面)。
ii.如果没配置,则控制台报映射查找不到,客户端展示404错误。
iii.如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误。
(b).存在,则执行下面的流程
(3).根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
(4).DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
(5).如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】。
(6).提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
(a).HttpMessageConveter(报文信息转换器): 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
(b).数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。
(c ).数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等。
(d).数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
(7).Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
(8).此时将开始执行拦截器的postHandle(…)方法【逆向】。
(9).根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。
(10).渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
(11).将渲染结果返回给客户端。