SpringMVC的执行流程,他的核心是什么?

先上图:

SpringMVC 架构(详细图解)以及执行流程

1、SpringMVC 执行流程

 SpringMVC 大体的执行流程图:

这张图只是展示出了 SpringMVC 的 MVC 三部分的处理情况,殊不知 SpringMVC 还有另外的三个组件,就是我们常说的 SpringMVC 三大组件:HandlerMapping 处理器映射器、HandlerAdapter 处理器适配器以及 ViewReslover 视图解析器,下面给出详细流程图:

这张图中我用了两种颜色的块状区域来表示,绿色表示 MVC 部分,橘色表示 SpringMVC 三大组件,这里共划分出了 11 个步骤,这里对这 11 个步骤进行一下说明:

1)用户发送请求至前端控制器 DispatcherServlet。

2)DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。

3) 处理器映射器根据请求 url 找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。

4) DispatcherServlet 通过 HandlerAdapter 处理器适配器调用处理器。

5) HandlerAdapter 执行处理器(handler,也叫后端控制器)。

6) Controller 执行完成返回 ModelAndView。

7) HandlerAdapter 将 handler 执行结果 ModelAndView 返回给 DispatcherServlet。

8) DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器。

9) ViewReslover 解析后返回具体 View 对象。

10) DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)。

11) DispatcherServlet 响应用户。

2、思考几个问题

既然了解了 SpringMVC 的执行流程,那么我们提出几个问题一起来思考一下,这里我会提供源码阅读的入口,帮助读者更加深入的了解 SpringMVC 的执行流程,具体如何实现的,感兴趣的读者可以深入源码研究:

前端控制器是如何找到对应的处理器的?

在 web.xml 中配置的前端控制器,这里我们就从它入手进行探索,这里我们打开前段控制器 DispatcherServlet 类,找到一个叫做 doDispatch 的方法:

看到这个英文注释了吗,“为当前请求确定处理器”,这就是前端控制器查找对应处理器的入口,我们点进去看一下,会发现你看到了 HandlerMapping 组件,并调用了 getHandler 方法,处理完成后返回了一个 HandlerExecutionChain 对象,是不是和我们流程图中的2、3步对应了呢。具体是如何查找的,可以继续跟踪下去,这里就不再深入了。

前端控制器是如何执行对应的处理器的?

这个问题我们还是看 doDispatch 方法,如下图所示,第一处标记代码根据注释可以知道是“为当前请求确定处理器适配器”,就是对 Handler 做适配,真正执行处理器的代码在第二处标记处。

我们先来看一下是如何查找对应的适配器的,点进 getHandlerAdapter 方法看一下,就看到了有一个组件 HandlerAdapter,它就是根据 HandlerAdapter 的 supports 方法进行适配的,这个 supports 方法实现例子会在下面体现。

再来看一下如何执行处理器的,ha.handle 方法有很多实现类,这里我们以 SimpleControllerHandlerAdapter 为例,看一下它的源码,就十分清晰了。

 

前端控制器是如何根据视图名称解析视图对象的?

有很多开发人用在使用 SpringMVC 的时候会有这样一个疑惑,为什么我在 Controller 中配置上视图名称,SpringMVC 就能找到对应的页面呢?感到很神奇,这里我们就要用到视图解析器 ViewReslover 了。依旧是 doDispatch 方法,我们找到下图标记的代码(处理前端请求):我们点进去,就能看到一个 render 方法,render 就是“渲染” 的意思,继续深入进去

 

到这里是不是就用到了 viewName(视图名称)了,这个方法叫做 resolveViewName 解析视图名称,是不是看着很亲切,我们继续深入进去: 

到这里就看到了 ViewResolver 了,然后循环遍历所有的 ViewResolver,如果能根据当前视图名称解析出视图对象,就直接将视图对象返回。具体是如何解析的,感兴趣的可以跟进到 viewResolver.resolveViewName 中进行查看(有多个实现类),这里就不再深入了。

默认配置

有很多读者看完上面三个问题后,就有疑问了,入门程序中并没有配置 SpringMVC 的三大组件,那么 SpringMVC 是如何完成工作的呢?其实 SpringMVC 是有默认配置的,这里我们一起看一下。

我们在 DispatherServlet 中找到 initStrategies 方法,如下图所示,可以看出这里初始化了很多配置,我们的三大组件都是在这里进行初始化的。

这里我们以 initHandlerMappings 方法进行讲解,找到 SpringMVC 的默认配置文件。进入 initHandlerMappings 方法,因为我们并没有进行配置(注解或者 Bean 标签),所以该方法中的前两种情况都会跳过,会来到最下面的默认情况处,调用了 getDefaultStrategies 方法,读取默认的配置文件。 

 

 在 getDefaultStrategies 方法中,有一个 defaultStrategies,我们当该类上面看一下:这里就是进行加载默认配置文件的地方,点击 DEFAULT_STRATEGIES_PATH 常量,找到了默认的配置配置文件。我们打开这个配置文件,就找到了我们想要的东西了。

该配置文件所处的位置如下所示:

 

常用组件说明

流程搞明白了,这里对用到的组件在进行一个汇总:

1、DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性

2、HandlerMapping:处理器映射器

HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

3、Handler:处理器

Handler 是继 DispatcherServlet 前端控制器的后端控制器,在 DispatcherServlet 的控制下Handler 对具体的用户请求进行处理。

由于 Handler 涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。

4、HandlAdapter:处理器适配器

通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

5、View Resolver:视图解析器

View Resolve r负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。

6、View:视图

SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。我们最常用的视图就是jsp。

SpringMVC 三大组件的配置

1、使用 bean 标签的方式配置映射器和适配器

1)RequestMappingHandlerMapping:注解式处理器映射器,对类中标记@ResquestMapping 的方法进行映射,根据 ResquestMapping 定义的 url 匹配ResquestMapping 标记的方法,匹配成功返回 HandlerMethod 对象给前端控制器,HandlerMethod 对象中封装url对应的方法 Method。

2)RequestMappingHandlerAdapter:注解式处理器适配器,对标记 @ResquestMapping的方法进行适配。

3)配置如下:

<!--注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

2、使用 mvc 标签的方式配置映射器和适配器

springmvc.xml 配置文件中使用 <mvc:annotation-driven/> 标签替代 bean 标签配置的注解处理器和适配器

<mvc:annotation-driven />

3、配置视图解析器

<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<property name="suffix" value=".jsp"/>
</bean>

InternalResourceViewResolver:默认支持JSP视图解析

viewClass:JstlView 表示 JSP 模板页面需要使用 JSTL 标签库,所以 classpath 中必须包含jstl 的相关 jar 包。此属性可以不设置,默认为JstlView。

prefix 和 suffix:查找视图页面的前缀和后缀,最终视图的址为:前缀+逻辑视图名+后缀,逻辑视图名需要在 controller 中返回的 ModelAndView 指定,比如逻辑视图名为 hello,则最终返回的jsp视图地址 “WEB-INF/jsp/hello.jsp”

在入门程序中,我们返回视图是这样写的:

modelAndView.setViewName("/WEB-INF/jsp/goodsList.jsp");

添加了视图解析器配置后,就可以写成下面的样子:

modelAndView.setViewName("goodsList");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值