前言:
小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个SpringMVC基础学习系列是用来记录我学习SpringMVC框架基础知识的全过程 (这个系列是参照B站狂神的SpringMVC最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将尽量以两天一更的速度更新这个系列,还没有学习SpringMVC框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧,加油吧,编程人!
特别提醒: 上期博客地址链接:SpringMVC基础学习之简单回顾MVC架构和Servlet的使用
今天我们来到了SpringMVC基础学习的第二站:初识SpringMVC,主要了解和学习SpringMVC的基本概念,中心控制器和执行原理。废话不多说,让我们开始今天的学习内容吧。
2.初识Spring MVC
2.1 Spring MVC 基本概念
2.1.1 什么是Spring MVC?
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架
官方文档地址链接:Spring MVC 5.3.4版本,不过这里推荐按照Spring MVC 4.3.21版本学习
2.1.2 Spring MVC主要特点
- 轻量级,简单易学
- 高效,基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置 (Maven项目也是如此)
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
2.1.3 SpringMVC和Spring的关系
Spring MVC和Spring的关系如下:
Spring本质上是个大杂烩,我们可以将SpringMVC中的所有要用到的Bean,注册到Spring的IOC容器中
2.1.4 为什么学习Spring MVC?
- Spring的Web框架围绕DispatcherServlet (调度Servlet) 设计
- DispatcherServlet的作用是将请求分发到不同的处理器 (从Spring 2.5 开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁)
- 正是由于Spring MVC具有简单、便捷和易学的特点,并且天生与Spring无缝集成(使用Spring的IOC和AOP) ;遵循约定优于配置,能够进行简单的junit测试,同时支持Restful风格、异常处理、本地化、国际化、数据验证、类型转换、拦截器等等,因此我们要进行学习
- 最重要的一点还是使用的人比较多,使用的公司也多
2.2 SpringMVC的中心控制器
在SpringMVC中,起中心控制器作用的是DispatcherServlet,接下来,我们来简单了解一下它
2.2.1 DispatcherServlet基本概念
- Spring的Web框架围绕DispatcherServlet设计,DispatcherServlet的作用是将请求分发到不同的处理器
- Spring MVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心DispatcherServlet来进行分派请求及提供其他功能
特别提醒:
DispatcherServlet实际上是一个Servlet类,它继承自HTTPServlet基类,为了了解其继承关系,这里我们简单地看一下它的相关源码
2.2.2 DispatcherServlet类源码浅析
1.查看DispatcherServlet类继承关系
- 首先DispatcherServlet这个中心控制器继承于FrameworkServlet类
public class DispatcherServlet extends FrameworkServlet { ... }
- 其次,抽象类FrameworkServlet又继承于HttpServletBean类,同时还实现了一个ApplicationContextAware接口
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { ... }
- 最后,抽象类HttpServletBean继承于HttpServlet基类
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { ... }
结论:因此,DispatcherServlet类确实继承于基类Servlet
接下来,我们再继续了解下DispatcherServlet这个中心控制器的基本变量有哪些?
2.查看DispatcherServlet基本变量
// 中心控制器
public class DispatcherServlet extends FrameworkServlet {
// 多部分解析器
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
// ...(省略中间部分代码)...
// 本地化解析器
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
// 处理器映射
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
// 处理器适配器
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
// 视图解析器
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
// ...(省略后面部分代码)...
}
还有DispatcherServlet类中的这个dosService方法主要作用是什么?
3.查看doService方法源码
// doService方法做什么事情: HttpServletRequest接收请求, HttpServletResponse来转发
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
this.logRequest(request);
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
// WebUtils把请求进行处理和调度
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();
// ...(后面省略部分代码)...
}
}
2.2.3 Servlet执行流程
- 客户端发送请求,请求被Servlet (控制器) 拦截,它主要负责调度、处理请求和适配URL以及跳转页面等 (一个项目中会存在多个Servlet)
- Servlet (控制器) 向Service (服务层) 请求数据,Service (服务层) 调用Dao(数据持久层) 查询数据
- Dao (数据持久层) 通过查询数据库获取数据,将数据交由Service (服务层) 进行处理
- Service (服务层) 将处理的数据返回给Servlet (控制器),Servlet (控制器) 根据返回的数据信息来跳转对应的jsp页面
总之,记住一句话,没有什么是加一层解决不来了的!
2.3 SpringMVC的执行原理
2.3.1 官方原理流程图
- 当用户或者客户端发送请求时,被前置的控制器拦截到请求
- 根据请求参数生成代理请求,找到请求对应的实际控制器
- 控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器
- 控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者
2.3.2 原理流程图完整版
下图为SpringMVC的一个较为完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线则需要开发者实现
简要分析执行流程:
-
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求, DispatcherServlet接收请求并拦截请求
假设请求的URL链接为:http://localhost:8080/SpringMVC/hello,将上面的URL拆分成三部分:
- http://localhost:8080表示服务器域名和端口号
- SpringMVC表示部署在服务器上的Web站点
- hello表示控制器名称
因此,上面的URL链接可以表示为:请求位于服务器 localhost:8080上的SpringMVC站点的hello控制器!
-
HandlerMapping表示处理器映射,由DispatcherServlet调用,HandlerMapping会根据请求URL查找Handler
-
HandlerExecution表示具体的Handler,其主要作用是根据URL查找控制器 (例如上面的URL查找控制器为: hello)
-
HandlerExecution将解析后的信息传递给DispatcherServlet (例如解析控制器映射等)
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
-
Handler让具体的Contorller执行
-
Controller将具体的执行信息返回给HandlerAdapter (如ModelAndView)
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
-
DispatcherServlet调用ViewResolver(视图解析器)来解析HandlerAdapter传递的逻辑视图名
-
ViewResolver( 视图解析器) 将解析的逻辑视图名传递给DispatcherServlet
-
DispatcherServlet根据ViewResolver(视图解析器) 解析的视图结果,调用具体的视图
-
最终将View视图呈现给用户
为了方便大家记忆,下面是经由整理简化的处理流程:
- 用户发送请求,前置控制器 (DispatcherServlet) 进行接收和拦截请求
- 前置控制器 (DispatcherServlet) 将URL链接发送给处理器映射 (HandlerMapping)
- 处理器映射 (HandlerMapping) 根据URL链接(或者xml和注解)查找具体的处理器 (Handler)
- 处理器执行器 (HandlerExecution) 将具体的处理器返回给前置控制器 (DispatcherServlet)
- 前置控制器(DispatcherServlet) 调用处理器适配器 (HandlerAdapter) 去执行处理器 (Handler)
- 处理器适配器 (HandlerAdapter) 调用具体的处理器 (Handler) 去执行对应的控制器(Controller)
- 控制器 (Controller) 返回视图模型 (ModelAndView) 给处理器适配器 (HandlerAdapter)
- 处理器适配器 (HandlerAdapter) 将视图模型返回前置控制器(DispatcherServlet)
- 前端控制器(DispatcherServlet) 将视图模型 (或视图逻辑名) 交由视图解析器 (ViewResolver) 进行处理
- 视图解析器 (VewResolver) 将解析的视图结果返回给前置控制器(DispatcherServlet)
- 前置控制器 (DispatcherServlet) 进行视图渲染,将视图模型(ModelAndView) 填充到request域
- 前置控制器 (DispatcherServlet) 向用户响应结果,即将具体的视图 (View) 呈现给用户
好了,今天的有关 初识SpringMVC 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!