SpringMVC 源码中常用类分析(一)

1、SpringMVC核心分发器DispatcherServlet:

主要类的父级关系为 : DispatcherServlet 继承自 FrameworkServlet 继承自 HttpServletBean 继承自 HttpServlt

  • HttpServletBean : 主要用于初始化工作,将web.xml中配置的参数设置到Servlet中。比如Servlet标签的的子标签init-param标签中配置的参数。
<servlet>
  <servlet-name>dispatcher</servlet-name>  
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  <load-on-startup>1</load-on-startup>  
  <init-param>
    <param-name>contextConfigLocation</param-name>  
    <param-value>classpath:springConfig/dispatcher-servlet.xml</param-value>  
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>  
  <url-pattern>/</url-pattern>  
</servlet-mapping>

比如上面这段配置,传递了contextConfigLocation参数,之后构造BeanWrapper,这里使用BeanWrapper,有2个理由:1. contextConfigLocation属性在FrameworkServlet中定义,HttpServletBean中未定义       2. 利用Spring的注入特性,只需要调用setPropertyValues方法就可将contextConfigLocation属性设置到对应实例中,也就是以依赖注入的方式初始化属性。

然后设置DispatcherServlet中的contextConfigLocation属性(FrameworkServlet中定义)为web.xml中读取的contextConfigLocation参数,该参数用于构造SpringMVC容器上下文。

  • FrameworkServlet : 主要用于关联Servlet和spring容器。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类的上下文,即web.xml配置中的ContextLoaderListener监听器初始化的容器上下文。

这里的根上下文是web.xml中配置的ContextLoaderListener监听器中根据contextConfigLocation路径生成的上下文。

<context-param>
  <param-name>contextConfigLocation</param-name>  
  <param-value>classpath:springConfig/applicationContext.xml</param-value>  
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>

比如这段配置文件中根据classpath:springConfig/applicationContext.xml下的xml文件生成的根上下文。

  • DispatcherServlet :主要用于初始化各个功能的实现类。比如异常处理、请求映射处理等等

2、SpringMVC如何找到对应controller:

首先是这个过程中所用到的重要的类和接口包括:HandlerMethod类、MethodParameter类、RequestCondition接口、RequestMappingInfo类、RequestMappingHandlerMapping类

  • HandlerMethod:Spring3.1版本之后引入的。 是一个封装了方法参数、方法注解,方法返回值等众多元素的类。
  • MethodParameter:HandlerMethod类中的parameters属性类型,是一个MethodParameter数组。MethodParameter是一个封装了方法参数具体信息的工具类,包括参数的的索引位置,类型,注解,参数名等信息。

    HandlerMethod在实例化的时候,构造函数中会初始化这个数组,这时只初始化了部分数据,在HandlerAdapter对请求处理过程中会完善其他属性,之后交予合适的HandlerMethodArgumentResolver接口处理。

  • RequestCondition:Spring3.1版本之后引入的。 是SpringMVC的映射基础中的请求条件,可以进行combine, compareTo,getMatchingCondition操作。这个接口是映射匹配的关键接口,其中getMatchingCondition方法关乎是否能找到合适的映射。

  • RequestMappingInfo:Spring3.1版本之后引入的。 是一个封装了各种请求映射条件并实现了RequestCondition接口的类。有各种RequestCondition实现类属性,patternsCondition,methodsCondition,paramsCondition,headersCondition,consumesCondition以及producesCondition,这个请求条件看属性名也了解,分别代表http请求的路径模式、方法、参数、头部等信息。

  • RequestMappingHandlerMapping:处理请求与HandlerMethod映射关系的一个类。

  • Web服务器启动的时候,SpringMVC到底做了什么:

先看AbstractHandlerMethodMapping的initHandlerMethods方法中。

我们进入createRequestMappingInfo方法看下是如何构造RequestMappingInfo对象的。

PatternsRequestCondition构造函数:

类对应的RequestMappingInfo存在的话,跟方法对应的RequestMappingInfo进行combine操作。

然后使用符合条件的method来注册各种HandlerMethod。

下面我们来看下各种RequestCondition接口的实现类的combine操作。

PatternsRequestCondition:

RequestMethodsRequestCondition:

方法的请求条件,用个set直接add即可。

其他相关的RequestConditon实现类读者可自行查看源码。

最终,RequestMappingHandlerMapping中两个比较重要的属性

private final Map<T, HandlerMethod> handlerMethods = new LinkedHashMap<T, HandlerMethod>();

private final MultiValueMap<String, T> urlMap = new LinkedMultiValueMap<String, T>();

T为RequestMappingInfo。

构造完成。

我们知道,SpringMVC的分发器DispatcherServlet会根据浏览器的请求地址获得HandlerExecutionChain。

这个过程我们看是如何实现的。

首先看HandlerMethod的获得(直接看关键代码了):

这里的比较器是使用RequestMappingInfo的compareTo方法(RequestCondition接口定义的)。

然后构造HandlerExecutionChain加上拦截器

特别申明,此文章转载自: https://www.cnblogs.com/fangjian0423/p/springMVC-directory-summary.html博客。

猜你喜欢

转载自blog.csdn.net/TNT_D/article/details/88101340