Spring MVC 学习笔记

1. Spring MVC核心类与接口

1.1 DispatcherServlet:前置控制器

Spring 提供的前置控制器,所有的请求都经过它来统一分发。DispatcherServlet 将请求分发给 Spring Controller 之前,需要借助于 Spring 提供的 HandlerMapping 定位到具体的 Controller
DispatcherServlet 也是间接最高继承了 HttpServlet.

1.2 HandlerMapping 接口:处理请求的映射

HandlerMapping 接口的实现类:

  • SimpleUrlHandlerMapping通过配置文件,把一个 URL 映射到 Controller 类上;
  • DefaultAnnotationHandlerMapping通过注解,例如 @RequestMapping,把一个 URL 映射到 Controller 类上;

1.3 HandlerAdapter 接口:处理请求的映射

Spring MVC 通过 HandlerAdapter 来实际调用处理函数。

例如:
AnnotationMethodHandlerAdapter:DispatcherServlet 中根据 HandlerMapping 找到对应的 Handler Method 后,首先检查当前工程中注册的所有可用的 HandlerAdapter,根据 HandlerAdapter 中的 supports() 方法找到可以使用的 HandlerAdapter
通过调用 HandlerAdapter 中的 handle() 方法来处理及准备 Handler Method 中的参数及 annotation (这就是 Spring MVC 如何将 Reqeust中的参数变成 Handler Method 中的输入参数的地方),最终调用实际的 Handler Method。
接口定义如下:

public interface HandlerAdapter {
    boolean supports(Object var1);

    @Nullable
    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

1.4 Controller接口:控制器

由于我们使用了 @Controller 注解,添加了 @Controller 注解的类就可以担任控制器(Action)的职责,所以我们并没有用到这个接口。

需要为并发用户处理请求,因此实现 Controller 接口时,必须保证线程安全并可重用。
一旦 Controller 处理完用户请求,则返回 ModelAndView 对象给 DispatcherServlet 前置控制器,ModelAndView 中包含了模型(Model)和视图(View)。

  • 从宏观角度考虑,DispatcherServlet 是整个 Web 应用的控制器;
  • 从微观考虑,Controller 是单个 Http 请求处理过程中的控制器;
  • ModelAndView 是 HTTP 请求过程中返回的模型(Model)和视图(View)。

1.5 HandlerInterceptor 接口:拦截器

1.6 ViewResolver 接口的实现类

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

  • JSP 需要用到 org.springframework.web.servlet.view.InternalResourceViewResolver
  • 模板引擎需要用到 org.springframework.web.servlet.view.tiles3.TilesViewResolver
  • 文件下载需要用到 org.springframework.web.servlet.view.BeanNameViewResolver

1.7 View 接口

View 也会有不同的实现类,例如返回 JSP 的 View 时需要用到 org.springframework.web.servlet.view.JstlView

1.8 LocalResolver 接口

1.9 HandlerExceptionResolver 接口:异常处理

1.10 ModelAndView 类

2. Spring 启动过程

对于一个 Web 应用,其部署在 Web 容器中(例如 Tomcat),Web 容器提供其一个全局的上下文环境,这个上下文就是 ServletContext其为后面的 Spring IoC 容器提供宿主环境。

在应用 web.xml 中会提供有 ContextLoaderListener,例如:



  org.springframework.web.context.ContextLoaderListener

在 Web 容器(例如 Tomcat)启动时,会触发容器初始化事件,此时 ContextLoaderListener 会监听到这个事件,其 contextInitialized 方法会被调用,在这个方法中,Spring 会初始化一个启动上下文,这个上下文被称为根上下文,即 WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是 XmlWebApplicationContext这个就是 Spring的 IoC 容器,其对应的 Bean 定义的配置由 web.xml 中的 context-param 标签指定。

public void contextInitialized(ServletContextEvent event) {
    this.initWebApplicationContext(event.getServletContext());
}

ContextLoaderListener 监听器初始化完毕后,开始初始化 web.xml 中配置的 Servlet,这个 Servlet 可以配置多个,以最常见的DispatcherServlet为例,这个 Servlet 实际上是一个标准的前端控制器,用以转发、匹配、处理每个 Servlet 请求。

DispatcherServlet 上下文在初始化的时候会建立自己的 IoC 上下文,用以持有 Spring MVC 相关的 Bean。在建立 DispatcherServlet 自己的 IoC 上下文时,会先从 ServletContext 中获取之前的根上下文(WebApplicationContext)作为自己上下文的 parent 上下文。有了这个 parent 上下文之后,再初始化自己持有的上下文。

当 Web 项目启动时,做初始化工作,所以我们大部分是配置在 web.xml 里面:



  Web Application

  
    contextConfigLocation
    classpath:applicationContext-*.xml
  

  
    org.springframework.web.context.ContextLoaderListener
  
  
  
    CharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
      encoding
      utf-8
    
  

  
    CharacterEncodingFilter
    /*
  

  
    springMVC_rest
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath:spring-mvc.xml
    
  

  
    springMVC_rest
    /
  


图片引用自 https://www.jianshu.com/p/dc64d02e49ac

Web应用部署初始化流程图

图片引用自 https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc

Spring MVC 学习笔记_第1张图片
image

3. DispatcherServlet 初始化过程

DispatcherServlet 继承了 FrameworkServletFrameworkServlet 继承了 HttpServletBeanHttpServletBean 继承了 HttpServlet 类。

第一步:HttpServletBean 类init() 方法

HttpServletBean 类有一个入口点就是重写了 init 方法。

  • 先通过 PropertyValues 获取 web.xml 文件 init-param 的参数值;
  • 然后通过 ResourceLoader 读取 .xml 配置信息;
  • BeanWrapper 对配置的标签进行解析和将系统默认的 bean 的各种属性设置到对应的 bean 属性;

第二步:FrameworkServlet 类 initServletBean() 方法

initWebApplicationContext() 初始化上下文,并作为值放到了 ServletContext 里,因为不同的 DispatherServlet 有对应的各自的上下文,而且上下文有设置父上下文和 id 属性等。
上下文项目启动时会调用 createWebApplicationContext() 方法。

第三步:DispatcherServlet 类 onRefresh() 方法

DispatcherServlet 初始化各个功能的实现类。比如异常处理、视图处理、请求映射处理等。

// 初始化上传文件解析器
initMultipartResolver(context);
// 初始化本地解析器
initLocaleResolver(context);
// 初始化主题解析器
initThemeResolver(context);
// 初始化映射处理器
initHandlerMappings(context);
// 初始化适配器处理器
initHandlerAdapters(context);
// 初始化异常处理器
initHandlerExceptionResolvers(context);
// 初始化请求到视图名翻译器
initRequestToViewNameTranslator(context);
// 初始化视图解析器
initViewResolvers(context);

4. DispatcherServlet 处理请求过程

图片引用自 https://terasolunaorg.github.io/guideline/5.0.0.RELEASE/en/Overview/SpringMVCOverview.html

Spring MVC 学习笔记_第2张图片
image

  • 用户向服务器发送请求,请求被 Spring 前置控制 Servelt DispatcherServlet 捕获;
  • DispatcherServlet 对请求 URL 进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回;
  • DispatcherServlet 根据请求获得 Handler,选择一个合适的 HandlerAdapter。(如果成功获得 HandlerAdapter 后,此时将开始执行拦截器的 preHandler(...) 方法)
  • 提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。 在填充 Handler 的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:
    • HttpMessageConveter:将请求消息(如 JSON、XML 等数据)转换成一个对象,将对象转换为指定的响应信息;
    • 数据转换:对请求消息进行数据转换。如 String 转换成 IntegerDouble 等;
    • 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等;
    • 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到 BindingResultError 中;
  • Handler 执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象;
  • 根据返回的 ModelAndView,选择一个适合的 ViewResolver 返回给 DispatcherServlet
  • ViewResolver 结合 ModelView,来渲染视图;
  • 将渲染结果返回给客户端;

引用:
WEB请求处理五:MVC框架请求处理
spring 启动过程

你可能感兴趣的:(Spring MVC 学习笔记)