![v2-2e169f165e4a297876346134d59b3ebc_1440w.jpg?source=172ae18b](http://img-01.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-2e169f165e4a297876346134d59b3ebc_1440w.jpg?source=172ae18b)
1. 摘要
本文旨在读者能通过本文知道SpringMVC是什么、干什么用的,在此基础上为了让读者能”知其然知其所以然”,还会介绍SpringMVC执行原理流程是怎么的,为的是让读者能对SpringMVC有更加深刻的认识和理解,在开发中能顺心应手,最后再通过一个简单的入门案例实现SpringMVC的功能,让读者切身感受下SpringMVC在项目中的作用。
2. SpringMVC概述
2.1. 什么是SpringMVC
SpringMVC就是一个Spring内置的MVC框架。
MVC框架,它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化等等),而且使用简单,与Spring无缝集成。支持 RESTful风格的URL请求。
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。
2.2. SpringMVC的作用
MVC模式(Model-View-Controller):解决页面代码和后台代码的分离。
3. SpringMVC原理
在没有使用SpringMVC之前我们都是使用Servlet在做Web开发。但是使用Servlet开发在接收请求参数,数据共享,页面跳转等操作相对比较复杂。servlet是java进行web开发的标准,既然springMVC是对servlet的封装,那么很显然SpringMVC底层就是Servlet,SpringMVC就是对Servlet进行深层次的封装。
3.1. 回顾MVC模式
--什么是mvc模式?
MVC分别是:模型model(javabean)、视图view(jsp/img)、控制器Controller(Action/servlet)。
C存在的目的就是为了保证M和V的一致性,当M发生改变时,C可以把M中的新内容更新到V中。
3.1.1. 原始MVC 模式
MVC模式最早使用在CS 架构(20世纪70+年代)
下面为原始的mvc模式:
![v2-73058869d5a3932f34e766004a6cc415_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-73058869d5a3932f34e766004a6cc415_b.jpg)
PS:目前web应用中,99%的项目都会使用mvc模式开发。
3.1.2. WEB开发的MVC
WEB开发从20世纪90+年代开始使用改进的MVC模式。在最原始的MVC上有一些改进
将model更广泛的使用,这样会比原始的mvc好多了。对MVC进行改进的主要是一些优秀的mvc框架,如Struts2,SpringMVC。
可以说,一个WEB项目如果缺少了MVC模式,那无异于一个人缺少了一颗有趣、阳光、乐光的心灵一样。
![v2-fd1a2508268ea7b8494bf40c9d07c397_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-fd1a2508268ea7b8494bf40c9d07c397_b.jpg)
3.2. SpringMVC执行流程和原理
![v2-b49c37600109b31e917074ac78ccfc26_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-b49c37600109b31e917074ac78ccfc26_b.jpg)
--SpringMVC执行流程:
01、用户发送出请求被前端控制器DispatcherServlet拦截进行处理。
02、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
03、HandlerMapping找到具体的处理器(查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
04、DispatcherServlet调用HandlerAdapter(处理器适配器)。
05、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
06、Controller执行完成返回ModelAndView对象。
07、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
08、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
09、ViewReslover解析ModelAndView后返回具体View(视图)给DispatcherServlet。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应View给用户。
--涉及组件分析:
1、前端控制器DispatcherServlet(不需要程序员开发)由框架提供,在web.xml中配置。
作用:接收请求,响应结果,相当于转发器,中央处理器。
2、处理器映射器HandlerMapping(不需要程序员开发)由框架提供。
作用:根据请求的url查找Handler(处理器/Controller),可以通过XML和注解方式来映射。
3、处理器适配器HandlerAdapter(不需要程序员开发)由框架提供。
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler中的方法。
4、处理器Handler(也称之为Controller,需要程序员开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。
作用:接受用户请求信息,调用业务方法处理请求,也称之为后端控制器。
5、视图解析器ViewResolver(不需要程序员开发)由框架提供。
作用:进行视图解析,把逻辑视图解析成真正的物理视图。
SpringMVC框架支持多种View视图技术,包括:jstlView、freemarkerView、ThymeleafView等。
6、视图View(需要工程师开发)
作用:把数据展现给用户的页面
View是一个接口,实现类支持不同的View技术(jsp、freemarker、pdf等)
--根据以上分析,SpringMVC需要程序员完成的工作有三个:
【1】配置前端控制器DispatcherServlet。
【2】开发后端控制器Handler/Controller。
【3】开发视图View。
接下来的入门案例,我们尝试只完成三个工作,看下能不能实现SpringMVC的功能。
4. 入门案例
4.1. 项目准备
4.1.1. 创建Maven项目(打包方式为war包)
![v2-db33f0b06961569abfeae2c3f701ba06_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-db33f0b06961569abfeae2c3f701ba06_b.jpg)
4.1.2. 添加spring-webmvc依赖
webmvc依赖包含beans、context、core、expression、commons-logging、aop、web、webmvc,换言之导入一个webmvc依赖,就间接导入了启动mvc框架的所有依赖。
--web:spring对web项目的支持。
--webmvc:SpringMVC核心包。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
![v2-4841c66676e0cc9dd63cfba8d883c6e9_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-4841c66676e0cc9dd63cfba8d883c6e9_b.jpg)
4.1.3. 添加servlet依赖
因为springmvc底层还是servlet,所以还必须添加serlvet依赖。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
4.2. 开发后端控制器Controller(与以前servlet类似)
public
4.3. 创建springmvc.xml配置文件
在src/main/resources/目录下创建springmvc.xml配置文件,并配置HelloController。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
name:给当前控制器取的一个名字,相当于Servlet中的资源名称,以便浏览器访问,必须以斜杠/开头
建议使用 name属性,不要使用id,因为早期版本 id 不支持特殊字符 如 /斜杠
-->
<bean name="/user/hello.do" class="org.brick.controller.UserController" />
</beans>
4.4. 开发视图View
在/WEB-INF下添加一个hello.jsp。
![v2-c81c61921bb28982c4894861dd578447_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-c81c61921bb28982c4894861dd578447_b.jpg)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String contextPath = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + contextPath + "/";
%>
<html>
<head>
<base href="<%=basePath%>">
<title>Title</title>
</head>
<body>
<h2>你好,${username}</h2>
</body>
</html>
4.5. 配置前端控制器DispatcherServlet
在web.xml中配置spring mvc核心(前端)控制器,并加载springmvc配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--
前端控制器:所有的请求都会经过此控制器,然后通过此控制器分发到各个分控制器
总控本质上还是一个Servlet,因为SpringMVC底层就是使用Servlet编写的
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 创建前端控制器的时候读取springmvc配置文件启动ioc容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- Tomcat启动就创建此对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置拦截路径url,所有以.do结尾的请求都会被前端控制器拦截处理 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
4.6. 启动项目
添加一个Tomcat服务器并部署项目若不清楚,参考:
JinwenChen:IDEA相关配置【集成Tomcat&项目部署】zhuanlan.zhihu.com![v2-0ef8abe44b78304c6c12d7df5f1d3396_180x120.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-0ef8abe44b78304c6c12d7df5f1d3396_180x120.jpg)
部署完项目之后,启动服务器。
4.7. 访问项目(使用PostMan)
![v2-4439aadc5e86a7d1c8f3d06971c43e3d_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-4439aadc5e86a7d1c8f3d06971c43e3d_b.jpg)
5. 小结
通过入门测试,我们确实完成三个工作:配置前端控制器、开发后端控制器、开发视图,就能通过浏览器或者测试工具(PostMan)访问我们的项目,即通过SpringMVC实现了MVC模式。但是通过XML配置的方式有一个问题:servlet的uri配置和serlvet的java代码是分开的,试想一下,如果servlet有几十个,上百个,那么我们需要定位serlvet对应的uri是不是要去配置文件里面逐个排查?这就很影响我们的开发效率了,特别是出现bug之后,本来心情就不愉快了,还要逐个逐个的排查,我们的心态会崩的,此时就需要使用springmvc另外一种开发模式:纯注解开发,来解决这个问题。
详见:
JinwenChen:SpringMVC【纯注解开发篇】zhuanlan.zhihu.com![v2-2e169f165e4a297876346134d59b3ebc_180x120.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=9ea099a4-1f2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-2e169f165e4a297876346134d59b3ebc_180x120.jpg)