SpringMVC 源码分析

SpringMVC的运行原理图

 

SpringMVC 源码分析

 

DispatcherServlet:
DispatcherServlet 继承结构

 

 

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

 

ServletConfigPropertyValues
ServletConfigPropertyValues HttpServletBean 的静态内部类。在其构造方法中通过传递的 ServletConfig 对象对 web.xml 文件中的 DispatcherServlet 节点中的参数进行解析处理。

 

BeanWrapper bw=PropertyAccessorFactory.forBeanPropertyAccess(this)
HttpServletBean 类型转换为 BeanWrapper 类型,从而能对 init-parameter 的值进行注入。

 

bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()))
注册自定义属性编辑器,遇到 Resource 类型的属性将会使用 ResourceEditor 进行解析

 

initBeanWrapper(bw)
该方法并未做什么,为了留给子类覆盖。

 

bw.setPropertyValues(pvs, true)
设置 DispatcherServlet 属性

 

initServletBean()
调用在 FrameworkServlet 中覆盖的该方法

 

 

FrameworkServlet
Servlet上下文与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文对象 , 实际类型ConfigurableWebApplicationContext。如果项目中用到spring了那么它有个父容器,既web.xml中配置的ContextLoaderListener监听器初始化的容器上下文

 

this.webApplicationContext =initWebApplicationContext():
可以看到,最重要的就是 this.webApplicationContext = initWebApplicationContext();这段代码,这个方法的作用是创建或刷新 WebApplicationContext 实例。如果项目中使用到了 spring,则进行父子容器关联。

 

initWebApplicationContext()方法:

如果项目中使用 spring 框架,并且在 web.xml 文件中配置了 Listener 来启动 spring。那么 在 监 听 器 中 spring 会 创 建 WebApplicationContext容器 。此时会将该容器转换为ConfigurableWebApplicationContext SpringMVC 容器。

 

如果没有在 web.mxl 文件中配置 Listener 那么此时 webApplicationContext为 空 则 去 ServletContext 中 根 据 attrname 查 找 。 如 果 为 找 到 , 执 行 createWebApplicationContext 方法来创建 SpringMVC 的容器。

 

createWebApplicationContext(rootContext)

 

createWebApplicationContext(ApplicationContext parent)

 

configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext  wac)

 

 

refresh()
解析配置文件初始化 SpringMVC IOC 容器环境。
解析 springmvc 配置文件:

等等。。。。。。。

 

DispatcherServlet
ContextRefreshListener

 

onRefresh(ApplicationContext context)

 

initStrategies(ApplicationContext context)
初始化 SpringMVC 其他组件:如多部件解析器、处理器映射器、处理器适配器、视图解析器等。

 

HandlerMapping 接口
初始化 HandlerMapping
initStrategies

 

 

initHandlerMappings

 

HandlerMapping 接口介绍
作用是根据当前请求的找到对应的 HandlerHandlerMethod(Controller中的方法)、Controller对象) ,并将Handler与一堆 HandlerInterceptor ( 拦 截 器 ) 封 装 到HandlerExecutionChain 对象中。在HandlerMapping 接口的内部只有一个方法:
HandlerExecutionChain getHandler(HttpServletRequest request);

 

HandlerMapping 接口实现类
HandlerMapping 实现类有两个分支,分别继承自 AbstractHandlerMethodMapping(得到 HandlerMethod)和 AbstractUrlHandlerMapping(得到 Controller t),它们又统一继承于AbstractHandlerMapping

 

 

AbstractHandlerMapping 抽象类
它实现了 HandlerMapping 接口中的 getHandler() 方法

 

AbstractHandlerMethodMapping
AbstractHandlerMethodMapping 这个分支获取的 Handler 的类型是 HandlerMethod,即这个 Handler 是一个方法,它保存了方法的信息(如 Method),这样一个 Controller 就可以处理多个请求了。

上 述 代 码 中 lookupHandlerMethod() 方 法 主 要 工 作 是 在 Map<T, HandlerMethod> handlerMethods 中找到 HandlerMethod,这里的 T HandlerMappingInfo,它封装了@RequestMapping 注解中的信息。

 

 

AbstractUrlHandlerMapping 抽象类
AbstractUrlHandlerMapping 这个分支获取的 Handler 的类型实际就是一个 Controller类。

 

Debug 走读 HandlerMapping

 

 

HandlerAdapter 接口
SpringMVC 中使用适配器模式来解决不同的 Handler 的执行。根据 Handler 来找到支持它的 HandlerAdapter,通过 HandlerAdapter 执行这个 Handler 得到 ModelAndView 象。

 

接口中的抽象方法
boolean supports(Object handler); 判断是否支持传入的 HandlerModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 用来使用 Handler 处理请求
long getLastModified(HttpServletRequest request, Object handler); 用 来 获 取 资 料 的Last-Modified

 

 HandlerAdapter 继承结构

 

AbstractHandlerMethodAdapter 抽象类

 

RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 实际就是执行@RequestMapping 注解的方法

 

handleInternal 方法
handlerInternal 方法中通过调用 invokeHandleMethod 方法执行 HandlerMethod 并返回一个 ModelAndView

 

invokeHandleMethod 方法

 

HttpRequestHandlerAdapter
HttpRequestHandlerAdapter 。是HttpRequestHandler的适配器可以执行HttpRequestHandler 类型的 Handler。其实就是 Controller中的handleRequest方法

 

SimpleControllerHandlerAdapter
SimpleControllerHandlerAdapter Controller 实现类的适配器类,其本质也是执行Controller 中的 handleRequest 方法。

 

SimpleServletHandlerAdapter
SimpleServletHandlerAdapter 其实是一个 Servlet 的适配器,其最终执行的方法是 Servlet的 service 方法

 

 

DispatcherServlet 中初始化处理器适配器
在配置文件中配置<mvc:annotation-driven />

 

未在配置文件中配置<mvc:annotation-driven />
[org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter@508cddf9,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@688a3991, org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter@6f15d 959]

 

ViewResolver 接口
根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 ViewView 是用来渲染页面的,也就是将 Model 填入模板中,生成 html 其他格式的文件。
 
 
 
接口中抽象方法
 
View resolveViewName(String viewName, Locale locale) throws Exception;
 
 
ViewResolver 接口结构
 
 
 
 
 
 
AbstractCachingViewResolver 抽象类
AbstractCachingViewResolver 是带有缓存的 ViewResolver,它每次解析时先从缓存里查找,如果找到视图就返回,没有就创建新的视图,且创建新视图的方法由其子类实现。
 
 
resolveViewName 方法
 
 
 
 
createView 方法
通过调用不同的子类中的 loadView 来指定不同视图解析器处理视图。
 
 
 
 
ResourceBundleViewResolver
ResourceBundleViewResolver 根据 views.properties 文件来解析视图,这个文件应位于classpath 路径下
 
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> 
    <!-- 设定属性文件名为 views --> 
    <property name="basename" value="views">
    </property>
 </bean>
user.(class)=org.springframework.web.servlet.view.JstlView
user.url=/WEB-INF/jsp/user.jsp
ModelAndView mv = new ModelAndView("user","msg", "aaa");

 
 
XmlViewResolver
 
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
  <property name="location"> 
  <value>spring-views.xml</value> 
  </property> 
</bean>
<bean id="internalResource" class="org.springframework.web.servlet.view.JstlView">
  <property name="url" value="/index.jsp" /> 
</bean>
ModelAndView mv = new ModelAndView("internalResource","msg", "aaa");

 
 
UrlBasedViewResolver
UrlBasedViewResolver 提供了拼接 URL 的方式来解析视图,通过 prefix 属性拼接一个前缀,通过 suffix 属性拼接一个后缀,就得到了视图的 URL。还可以加入 redirect: forword: 前缀,使用 redirect: 前缀会调用 HttpServletResponse 对象sendRedirect() 方法进行重定向,使用 forword: 前缀会利用 RequestDispatcher forword 方式跳转到指定的地址。另外,使用时还要指定viewClass 属性,表示要解析成哪种 View
 
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> 
   <property name="prefix" value="/WEB-INF/" /> 
   <property name="suffix" value=".jsp" /> 
   <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView" /> 
</bean>

 
 
 
 
InternalResourceViewResolver
 
InternalResourceViewResolver UrlBasedViewResolver 的 子 类 , 将InternalResourceView 作为默认的 View 类,但如果当前 classpath 中有 jstl jar 包时则使用 JstlView 作为 view 来渲染。
 
 
UrlBasedViewResolver
 
 
 
InternalResourceViewResolver
 
 
 
 
 
View 接口
视图渲染器,在该接口中定义了渲染视图的抽象方法。
何为渲染:所谓渲染其实就是将 Model 中的数据放到 HttpServletRequest 中传递 jsp
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
 
 
 
接口结构
 
 

 

InternalResourceView
继承自 AbstractUrlBasedView 抽象类的类,表示 JSP 视图

 

ViewResolver
DispatcherServlet 初始化视图解析器

posted @ 2019-12-11 08:56  sakura-yxf  阅读(205)  评论(0)    收藏  举报