SpringMVC的源码解析

作者:xjz1842 时间:2022-10-05 20:12:18 

学习java的人都知道spring,springMVC,mybatis等框架,像structs2这样的框架是基于servlet以外实现的,而springMVC是基于servlet容器实现的,

本文将分析SpringMVC的核心分发器DispatcherServlet的初始化过程以及处理请求的过程,让读者了解这个入口Servlet的作用。

在分析DispatcherServlet之前,我们先看下DispatcherServlet的继承关系,

SpringMVC的源码解析

HttpSerlvetBean继承自HttpServlet。

HttpServletBean覆写了init方法,对初始化过程做了一些处理。 以下是初始化的代码:

SpringMVC的源码解析

首先,ServletConfigPropertyValues是HttpServletBean的静态类,构造过程会使用ServletConfig对象找出web.xml文件中配置参数,并设置到ServletConfigPropertyValue,使用BeanWrapper来构造DispatcherServlet, 获取ServletContextResourceLoader的资源加载器,然后注册资源编辑器,初始化BeanWrapper对象,设置DispatcherServlet属性,默认初始化ServletBean不做任何处理,子类覆盖该方法可以做任何事情,

以下是web.xml文件配置:

SpringMVC的源码解析

这段配置初始化参数为contextConfigLocation,后来构造的是BeanWrapper对象, 由于contextConfigLocation在FrameworkServlet中定义,但是没有在HttpServletBean中定义,利用Spring的注入特性,只需要调用setContextConfigLocation方法,就可以将contextConfigLocation设置到对应的实例当中,然后设置DispatcherServlet中contextConfigLocation(FrameworkServlet中定义)的属性,为web.xml读取contextConfigLocation参数,该资源文件用构造SpringMVC的容器的上下文。

下面看下FrameworkServlet这个类,FrameworkServlet继承自HttpServletBean。

以下是initServletBean的代码:

SpringMVC的源码解析

首先第一步是初始化WebApplicationContext,它是继承于ApplcationContext的接口,ApplcationContext是Spring容器的上下文,Servlet和Spring容器关联的作用,然后初始化FrameWorkServlet,其实它空的,什么也做,子类重写这个方法,可以做任何处理,不过DispatcherServlet并重写这个方法。

下面是初始化initWebApplicationContext的具体实现逻辑: 

SpringMVC的源码解析    

首先,得到根路径,DistpatcherServlet有个WebApplication为参数的构造函数,如果注入了WebApplication 这个对象,就会执行上图代码。

SpringMVC的源码解析

FrameworkServlet中有个String类型的contextAttribute的变量名,以它为key在ServletContextWebApplicationContext,一般不会设置,contextAttribute属性,也就说,wac开始是null;接下来就是创建WebApplicationContext,并设置根上下文为父上下文,然后配置ServletConfig,ServletContext等到这个上下文,这个类中有个函数onReFresh是一个模版方法,在WebApplication成功创建后就会调用,FrameworkServlet的实现类,就会重写这个方法,并将创建的容器上下文设置到ServletContext中,这里的根上下文是web.xml中配置的ContextLoaderListener * 中根据contextConfigLocation路径生成的上下文。

SpringMVC的源码解析

比如这段配置文件中根据classpath:context-*.xml下的xml文件生成的根上下文。

接着看一下DispatcherServlet重写了FrameworkServlet中onReFresh方法,

SpringMVC的源码解析

可以看到initStrategies方法中,在初始化各种各种策略接口的实现类, 后面再一一分析各个策略接口的实现的详细介绍。

总结一个三个类的作用:

HttpServletBean 主要做一些初始化的工作,将web.xml中配置的参数设置到Servlet中。比如servlet标签的子标签init-param标签中配置的参数。

FrameworkServlet 将Servlet与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类上下文,web.xml中配置的ContextLoaderListener * 初始化的容器上下文。

DispatcherServlet 主要是初始化一些各个策略接口的实现。比如请求处理,试图处理。处理的适配等。

DispatcherServlet请求处理过程:

先看下HttpServlet提供的方法用于处理请求,service使用了模版模式,对于HttpServlet的get请求,调用doGet方法,post请 求,调用doPost方法........

SpringMVC的源码解析

在看下处理processRequest函数

SpringMVC的源码解析

首先,获取于当前线程绑定的LocaleContext和ServletRequestAttributes对象,initContextHoers函数就是让新构造的LocaleContex和requestAttributes进行关联,这个关联使用ThreadLocal完成,doService方法是抽象方法,具体由DispatcherServlet实现。

SpringMVC的源码解析

最后调用resetContextHolders函数重置LocaleContext和RequestAttribute对象,解除LocaleContext和RequestAttribute对象的绑定。执行成功后,发布ServletRequestHandlerEvent事件,可以通过注册 * 来监听该事件的发布。注册的 * 类型为ApplicationListener接口类型。

接下来是DispatcherServlet的doService方法.

SpringMVC的源码解析

如果该请求是include的请求,那么保留一份快照版本的request域中的数据,doDispatch方法之后,这个快照版本的数据将会覆盖新的Requet域的数据。

然后在request中设置一些属性,最后doDispatcher进行请求分发处理。

doDispatch方 * 能大致过程如下:

首先根据请求的路径,通过RequestMapping的注解映射,找到HandlerMethod(也就是对应Controller中的方法),然后匹配路径对应的 * ,有了HandlerMethod和 * 构造个HandlerExecutionChain对象。HandlerExecutionChain对象的获取是通过HandlerMapping接口提供的方法中得到。

有了HandlerExecutionChain之后,通过handlerAdapter对象进行适配处理,得到ModelAndView对象,HandlerMethod内部handle的时候,使用各种HandlerMethodArgumentResolver实现类处理HandlerMethod的参数,使用各种HandlerMethodReturnValueHandler实现类处理返回值,最终返回值被处理成一个ModelAndView对象,这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理.

总结: 本文主要分析DispatcherServlet及其父类FrameworkServlet和HttpServletBean它们的作用。以及一个请求到处理返回,大致过程的分析。

来源:http://www.cnblogs.com/xjz1842/p/6377732.html

标签:SpringMVC
0
投稿

猜你喜欢

  • Android SDK命令行工具Monkey参数及使用解析

    2023-07-13 17:00:33
  • 对C#中public、private、protect的区别说明

    2021-05-30 22:11:21
  • JAVA图片水印开发案例详解

    2023-06-20 02:06:53
  • SpringBoot如何使用ApplicationContext获取bean对象

    2023-06-28 20:36:55
  • Java Mybatis中的 ${ } 和 #{ }的区别使用详解

    2021-07-02 22:35:27
  • Mac Android Studio 3.0 Terminal 中文乱码问题处理

    2023-08-12 13:42:09
  • Android实现美团外卖底部导航栏动画

    2022-09-21 20:09:13
  • Android获取SD卡路径及SDCard内存的方法

    2021-12-30 17:04:58
  • java实现图片转base64字符串 java实现base64字符串转图片

    2023-07-19 10:42:44
  • Android控件之TabHost用法实例分析

    2021-07-19 10:35:21
  • Service Activity的三种交互方式(详解)

    2022-03-16 20:55:08
  • c# Selenium爬取数据时防止webdriver封爬虫的方法

    2023-06-24 07:50:51
  • C#递归实现回文判断算法

    2022-06-14 13:45:16
  • Android仿今日头条顶部导航栏效果的实例代码

    2022-04-02 23:18:03
  • C#实现GZip压缩和解压缩入门实例

    2021-05-29 08:20:45
  • Android中断线程的处理方法

    2023-07-31 11:51:55
  • 解决IDEA中 Ctrl+ALT+V这个快捷键无法使用的情况

    2022-02-27 07:51:36
  • Java实现将PDF转为PDF/A

    2023-03-16 00:54:22
  • Rxjava功能操作符的使用方法详解

    2021-06-10 06:57:16
  • Java springboot yaml语法注解

    2023-06-17 08:13:35
  • asp之家 软件编程 m.aspxhome.com