【SpringMVC笔记08】SpringMVC执行流程介绍

这篇文章,主要介绍SpringMVC框架中的核心组件,以及SpringMVC框架的执行流程。

目录

一、SpringMVC核心组件

1.1、DispatcherServlet

1.2、HandlerMapping

1.3、HandlerAdapter

1.4、Handler

1.5、ViewResolver

1.6、View

二、SpringMVC执行流程

2.1、执行流程

2.2、SpringMVC执行流程源码解读


一、SpringMVC核心组件

SpringMVC框架,本质上就是Servlet,只不过SpringMVC框架对Servlet进行了封装,形成了很多的组件类,通过这些组件类的协调合作,从而实现。下面介绍一下SpringMVC框架中的核心组件及其功能。

1.1、DispatcherServlet

DispatcherServlet,叫做:前端控制器,从名称上面就可以知道,它是一个Servlet类,这个类是整个SpringMVC框架的核心,项目中的所有的HTTP请求首先都会被DispatcherServlet进行处理,并且通过调用其他组件完成整个请求和响应过程。

DispatcherServlet主要作用:

  • 统一的处理请求和响应。
  • 协调和调度其他组件的使用。

SpringMVC框架里面,我们需要在【web.xml】配置文件里面,添加【DispatcherServlet】的配置,拦截路径必须设置为【/】斜杠。

<!-- 配置 DispatcherServlet 前端控制器 -->
<servlet>
    <!-- servlet 名称 -->
    <servlet-name>springMVC</servlet-name>
    <!-- servlet处理类 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 设置 SpringMVC 配置文件 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- 设置启动时候加载 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet映射路径 -->
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <!-- 拦截【/】请求,即:所有请求,除了jsp文件的请求 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

下面看下DispatcherServlet类的继承关系。

  • DispatcherServlet是继承自【FrameworkServlet】类,而【FrameworkServlet】继承自【HttpServletBean】,【HttpServletBean】继承自【HttpServlet】,到这里,看到HttpServlet这个类是不是很熟悉了呢???HttpServlet不就是之前学习Servlet时候经常使用到的类吗???
  • 所以,这也是为什么说DispatcherServlet本质上就是Servlet的原因,因为它继承自HttpServlet类。

  • DispatcherServlet既然是Servlet,那么它就满足Servlet的生命周期,也就是初始化、服务阶段、销毁阶段。
  • 要看源码,就先从DispatcherServlet类中的【doService()】方法开始查看即可。

1.2、HandlerMapping

HandlerMapping,叫做:处理器映射器,它的主要作用是:根据当前HTTP的请求url,找到对应处理的Handler处理器,也就是说,当前这个请求应该被哪个类里面的哪个方法进行处理。

仔细想一下,我们在使用SpringMVC框架进行开发的时候,是不是都会写一个Controller类,然后这个Controller类里面,每个方法都会对应一个url,HandlerMapping的作用就是将【url】和【method】进行关联起来,相当于一个【Map<url, HandlerMapping>】之后有HTTP请求进来的时候,直接根据url找到对应的Handler。

HandlerMapping是一个接口,接口里面只有一个【getHandler()】抽象方法,如下所示:

HandlerMapping具有多个实现类,如下所示:

1.3、HandlerAdapter

HandlerAdapter,叫做:处理器适配器。通过前面HandlerMapping处理器映射找到具体的Handler之后,这个时候就需要执行对应的处理方法,SpringMVC框架采用了适配器模式,通过HandlerAdapter处理器适配器去执行具体Handler的方法。

HandlerAdapter是一个接口,主要有三个方法,其中核心的方法是:【handle()】方法。

  • 【handle()】方法的作用:执行具体的Handler,然后返回ModelAndView对象。
  • 【supports()】方法的作用:判断找到的Handler是否可以执行,如果不可以执行,SpringMVC会抛出异常(No adapter for handler)。
  • 【getLastModified()】方法的作用:返回最后一次修改的序号,默认是【-1】。

1.4、Handler

Handler,叫做:处理器,其实就是我们常说的Controller控制器,这个Handler是我们自己编写的,它是SpringMVC框架里面唯一一个由我们开发人员自己编写的类,在这个Handler里面我们需要执行每个url对应的处理方法。

SpringMVC框架里面没有Handler接口,这里说的Handler是指我们常说的Controller控制器,而SpringMVC框架里面有一个叫做【Controller】的接口,里面只有一个抽象方法【handleRequest()】。

开发过程里面,我们自己写的Handler需要实现Controller接口,然后重写handleRequest方法,然后在这个方法里面完成业务逻辑的处理。

1.5、ViewResolver

ViewResolver,叫做:视图解析器。SpringMVC处理数据之后,根据具体的视图名称进行解析,解析之后得到具体的视图模板View对象。SpringMVC中有多种视图可以使用,具体参考我之前写的笔记【【SpringMVC笔记05】SpringMVC中的视图解析器】。

ViewResolver是一个接口,里面只有一个抽象方法【resolveViewName()】,从名称上面就可以看出,这个方法的作用是解析视图名称,resolveViewName根据视图名称viewName找到具体的View模板。

1.6、View

View,叫做:视图,它的作用是根据具体的数据进行渲染,然后将渲染的页面展现给用户。

View是一个接口,里面只有两个方法,其中核心方法是【render()】,render中文含义表示渲染的意思,也就是说View接口里面的render()方法作用是将视图和数据进行渲染后响应给客户端浏览器进行显示。

SpringMVC框架底层就是通过上面这些组件实现的,下面看下SpringMVC框架底层的具体执行流程。

二、SpringMVC执行流程

2.1、执行流程

SpringMVC框架,所有的HTTP请求都是会被DispatcherServlet类拦截,然后通过DispatcherServlet进行各组件的调度,最终完成每个请求的处理和响应操作,下面看下SpringMVC框架具体的执行流程。

 SpringMVC执行流程概述

  • 当客户端发起一次HTTP请求时候,会被【DispatcherServlet】类中的【doService()】方法处理。
  • 【DispatcherServlet】类会调用【HandlerMaping】组件,获取到具体处理当前请求的【Handler】。
  • 获取到【Handler】之后,【DispatcherServlet】组件通过【HandlerAdapter】处理器适配器执行具体的【Handler】,并且返回【ModelAndView】对象。
  • 【DispatcherServlet】接收到【ModelAndView】对象之后,接着调用【ViewResolver】视图解析器组件,根据【viewName】视图名称获取到具体的【View】视图模板。
  • 【DispatcherServlet】根据具体的【View】视图对象,调用【render()】方法将数据和模板进行渲染,渲染完成之后,最终响应给客户端。

2.2、SpringMVC执行流程源码解读

现在有一个HTTP请求进入到SpringMVC里面,会进入到【DispatcherServlet】类中的【doService()】方法里面。

 【doService()】方法主要作用是记录请求日志,往request作用域里面存放一些数据,例如:web容器对象,主题等。

【doService】方法会调用【doDispatch()】方法,真正进行HTTP请求的处理和响应功能,如下所示:

 【doDispatch()】方法里面,会调用【getHandler()】方法,用于获取当前HTTP请求应该被哪个【Handler】处理,但是【getHandler()】方法不是直接返回Handler,而是返回一个HandlerExecutionChain处理器执行链。

下面看下【getHandler()】方法的源码:

getHandler()方法就是从事先做好映射关系的HandlerMapping里面找到当前请求处理的Handler。

这里是不是会有个疑问呢???这个url和Handler是什么时候进行关系映射的呢???其实,SpringMVC在执行的时候,首先会调用一个【initStrategies()】方法,这个方法作用是初始化一些策略,什么意思呢???

其实就是在这个【initStrategies()】方法里面初始化一些数据,例如:将每个请求URL和Handler进行初始化,初始化处理器适配器,视图解析器等等,如下所示。

好了,继续回到getHandler()方法,遍历所有的HandlerMapping处理器映射器,调用mapping的handler()方法,但是handler()方法是个抽象方法,查看它具体的实现类,最终会调用【AbstractUrlHandlerMapping】类中的【getHandlerInternal()】方法。

SpringMVC框架在解析HTTP请求路径的时候,是会通过【UrlPathHelper】这个类,这是一个专门用于路径处理的工具类。当我们获取到当前HTTP的URI之后,就会调用lookupHandler()方法,从handlerMap里面根据URI获取具体的Handler对象。

如果能够获取到Handler对象,则直接返回,否则返回默认的Handler。SpringMVC框架获取到具体的Handler对象之后,就需要执行这个Handler对象的方法,此时调用【getHandlerAdapter()】方法,获取具体执行Handler的处理器适配器HandlerAdapter。

 【getHandlerAdapter()】方法作用很简单,就是遍历所有的handlerAdapter处理器适配器,判断某个处理器适配器能否执行当前的Handler,如果可以则返回Adapter,否则抛出异常:No adapter for handler

 既然SpringMVC拿到了执行Handler的处理器适配器HandlerAdapter,这就可以执行Handler了,通过调用handle()方法,完成具体Handler的调用。

 

在handle()方法,会从具体的实现类完成Handler的执行,一般都是Controller类型的Handler,SpringMVC会通过SimpleControllerHandlerAdapter类将之前获取到handler对象转换成Controller类型,然后调用handleRequest()方法。

handleRequest()方法里面会从request请求里面,获取到URI,然后根据URI请求路径从viewNameCache缓存里面获取具体的视图名称。

DispatcherServlet获取到ModelAndView对象之后,SpringMVC还会调用applyDefaultViewName方法,进一步判断是否存在视图名称,如果不存在视图名称,那么SpringMVC会设置一个默认的视图名称viewName。

接着,SpringMVC调用applyPostHandle方法,这个方法主要是用于在执行Controller之后,先执行对应的Interceptor拦截器对象postHandle()方法。

最后,SpringMVC一系列的操作都执行完成后,就要开始渲染视图了,SpringMVC调用processDispatchResult方法,用于处理转发结果,在下面这个方法里面,首先判断是否存在异常,如果出现异常了,直接抛出异常;否则,调用render()方法进行视图的渲染,当我们的视图渲染完成之后,如果存在Interceptor拦截器,那么就会调用拦截器的afterCompletion方法(拦截器生命周期的最后一个方法,在试图渲染完成之后执行)。

 SpringMVC是如何调用render()方法进行视图渲染的呢?下面一起看下render()方法的代码。

render()方法首先会根据viewName,调用resolveViewName()方法找到具体的视图摸板View。resolveViewName方法里面,就是通过ViewResolver视图解析器,根据视图名称返回具体的视图对象View。

ViewResolver视图解析器,是根据ViewName从web容器里面找到对应的Bean对象,这个Bean对象就是我们配置了的哪个视图解析器对象。

SpringMVC框架最终进行视图渲染的时候,要看采用了哪个视图模板,例如:Servlet、Thymeleaf、Freemarker等等,不同的视图会调用不同的视图渲染实现类,如果我们配置的内部资源视图解析器InternalResourceViewResolver,那么就会调用InternalResourceView来完成视图渲染。

 InternalResourceView里面,最终是通过请求的转发或者包含完成视图的跳转。

到这里,SpringMVC整个的执行流程就介绍完了。

综上,这篇文章结束了,主要介绍SpringMVC框架中的核心组件,以及SpringMVC框架的执行流程。


版权声明:本文为qq_39826207原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。