SpringMVC 源码分析

一、回顾 SpringMVC  原理

二、 SpringMVC  源码分析

1 DispatcherServlet

1.1 DispatcherServlet  继承结构

  1.1.1 HttpServletBean

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

       1.1.1.1 ServletConfigPropertyValues :

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

       1.1.1.2 BeanWrapper bw=PropertyAccessorFactory.forBeanPropertyAccess(this) :

将 HttpServletBean 类型转换为 BeanWrapper 类型,从而能对 init-parameter 的值进行注入。

       1.1.1.3 bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader,getEnvironment())) :

注册自定义属性编辑器,遇到 Resource 类型的属性将会使用 ResourceEditor 进行解析

        1.1.1.4 initBeanWrapper(bw) :

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

        1.1.1.5 bw.setPropertyValues(pvs, true) :

设置 DispatcherServlet 属性

        1.1.1.6 initServletBean() :

调用在 FrameworkServlet 中覆盖的该方法

1.1.2 FrameworkServlet

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

1.1.2.1 this.webApplicationContext =initWebApplicationContext():

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

1.1.2.2 initWebApplicationContext() 方法:

获取 spring 框架的根容器

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

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

1.1.2.3 createWebApplicationContext(rootContext) :

1.1.2.4 createWebApplicationContext(ApplicationContext parent) :

1.1.2.5 configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) :

1.1.2.6 refresh() :

解析配置文件初始化 SpringMVC 的 IOC 容器环境。

解析 springmvc 配置文件:

初始化所有的 Bean 对象

解析命名空间

1.1.3DispatcherServlet

1.1.3.1 ContextRefreshListener

1.1.3.2 onRefresh(ApplicationContext context) :

1.1.3.3 initStrategies(ApplicationContext context) :

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

1.2 Debug  走读 DispatcherServlet

2 HandlerMapping  接口

2.1 初始化 HandlerMapping

2.1.1 initStrategies

2.1.2 initHandlerMappings

2.2 HandlerMapping  接口介绍

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

2.3 HandlerMapping  接口实现类

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

2.3.1 AbstractHandlerMapping  抽象类

它实现了 HandlerMapping 接口中的 getHandler() 方法

2.3.1.1 AbstractHandlerMethodMapping

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

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

2.3.1.2 AbstractUrlHandlerMapping  抽象类

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

2.4 Debug  走读 HandlerMapping

3 HandlerAdapter  接口

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

3.1 接口中的抽象方法

boolean supports(Object handler); 判断是否支持传入的 Handler

ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 用来使用 Handler 处理请求

long getLastModified(HttpServletRequest request, Object handler); 用 来 获 取 资 料 的Last-Modified 值

3.2HandlerAdapter  继承结构

3.3 AbstractHandlerMethodAdapter  抽象类

利用 RequestMappingHandlerMapping 获取的 Handler 是 HadnlerMethod 类型,它代表 Controller 里要执行的方法。handlerInternal 是子类 RequestMappingHandlerAdapter 中的方法。

3.4 RequestMappingHandlerAdapter  类

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

3.4.1 handleInternal  方法

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

3.4.2 invokeHandleMethod  方法

3.5 HttpRequestHandlerAdapter  类

HttpRequestHandlerAdapter 。 是 HttpRequestHandler 的 适 配 器 可 以 执 行

HttpRequestHandler 类型的 Handler。其实就是 Controller 中的 handleRequest 方法

3.6 SimpleControllerHandlerAdapter  类

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

3.7 SimpleServletHandlerAdapter  类

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

3.8 Debug  走读 DispatcherServlet  中初始化处理器适配器

3.8.1 在配置文件中配置<mvc:annotation-driven />

{org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#
0=org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@4e
afea11,
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter=org.springframework.we
b.servlet.mvc.HttpRequestHandlerAdapter@1a4d6190,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter=org.springframewor
k.web.servlet.mvc.SimpleControllerHandlerAdapter@710d6556}

3.8.2 未在配置文件中配置<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]

4 ViewResolver  接口

根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Model 填入模板中,生成 html 或其他格式的文件。

4.1 接口中抽象方法

View resolveViewName(String viewName, Locale locale) throws Exception;

4.2 ViewResolver  接口结构

4.3 AbstractCachingViewResolver  抽象类

AbstractCachingViewResolver 是带有缓存的 ViewResolver,它每次解析时先从缓存里查找,如果找到视图就返回,没有就创建新的视图,且创建新视图的方法由其子类实现。

4.3.1 resolveViewName  方法

4.3.2 createView  方法

通过调用不同的子类中的 loadView 来指定不同视图解析器处理视图。

4.4 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");

4.5 XmlViewResolver  类

XmlViewResolver 根据 xml 文件来解析视图

<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");

4.6 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>

4.7 InternalResourceViewResolver  类

InternalResourceViewResolver 是 UrlBasedViewResolver 的 子 类 , 将InternalResourceView 作为默认的 View 类,但如果当前 classpath 中有 jstl 的 jar 包时则使用 JstlView 作为 view 来渲染。

  4.7.1 UrlBasedViewResolver  类

  4.7.2 InternalResourceViewResolver  类

5 View  接口

视图渲染器,在该接口中定义了渲染视图的抽象方法。

何为渲染:所谓渲染其实就是将 Model 中的数据放到 HttpServletRequest 中传递 jsp。

void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

5.1 接口结构

5.2 InternalResourceView  类

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

5.3 Debug  走读 ViewResolver

  5.3.1 DispatcherServlet  初始化视图解析器

   5.3.2 ViewResolver  处理 ModelAndView

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

plenilune-望月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值