一、Spring MVC概述
1.1为什么使用Spring MVC?
servlet案例:
java
@WebServlet("/addUser") //1、该Servlet的URL映射为"/addUser"
public class AddUserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
//2、接收前台传递的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
Integer age = Integer.parseInt(req.getParameter("age"));
String address = req.getParameter("address");
userService.addUser(username, password, sex, age, address);
resp.sendRedirect("selectUser");
}
}
- servlet缺陷:
1.一个servlet实例只能处理一个请求
2.参数接收太麻烦
1.2 MVC 设计模式
MVC 是一种软件分层设计模式,将应用分为三层:
- Model(模型层) :JavaBean,分为两类
- 数据承载 Bean:如 pojo/User、Student(存储业务数据)
- 业务处理 Bean:如 Service、Dao(处理业务逻辑 / 数据访问)
- View(视图层):HTML/JSP 页面,负责交互和数据展示
- Controller(控制层):Servlet,接收请求、响应浏览器
MVC 工作流程:
View----->Controller----->Model
用户通过视图层发起请求 → 控制器接收请求 → 调用模型层处理数据 → 模型层返回结果给控制器 → 控制器选择视图渲染数据 → 响应给浏览器
MVC 和三层架构的关系:
| 对比维度 | 三层架构 | MVC |
|---|---|---|
| 分层关系 | 典型上下依赖关系,上层依赖下层 | 相互协作关系,不存在上下层 |
| 划分依据 | 基于业务逻辑划分 | 基于页面划分 |
1.3 SpringMVC 介绍
- SpringMVC 是 Spring 框架的核心模块,基于 MVC 设计模式的轻量级 Web 框架(本质等价于 Servlet)
- 是 Java EE 项目表述层开发的首选方案,提供了完备的控制层解决方案
二、SpringMVC 入门案例
2.1 环境搭建
2.1.1 创建工程并添加 Web 支持
- 新建 Maven 工程,右键选择
Add framework support... - 勾选 Web Application,添加 Web 支持
- 将 web 目录拖拽到 main 目录下,重命名为 webapp(注意:先加框架支持,再设置打包方式)

注意:
-
先添加框架支持,再设置打包方式
-
将web目录要拖拽到main目录下,并改名为webapp
2.1.2 配置 pom.xml
xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hg</groupId>
<artifactId>SpringMVC_day01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式-->
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!--端口号-->
<port>8080</port>
<!--项目名-->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2 编写核心代码
2.2.1 前端页面(index.jsp)
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>SpringMVC入门</title>
</head>
<body>
<a href="/hello">hello springmvc</a>
</body>
</html>
2.2.2 控制器(HelloController)
java
@Controller
public class HelloController {
// 建立请求URL和方法的映射关系
@RequestMapping("/hello")
public ModelAndView hello() {
// 封装模型数据和视图名称
ModelAndView mv = new ModelAndView();
// 等价于request.setAttribute("hello", "欢迎你 springmvc!!")
mv.addObject("hello", "欢迎你 springmvc!!");
// 设置逻辑视图名(由视图解析器拼接为物理路径)
mv.setViewName("success");
return mv;
}
}
2.2.3 SpringMVC 配置文件(springmvc.xml)
xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描注解所在的包 -->
<context:component-scan base-package="com.hg"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 开启SpringMVC注解支持: 配置HandlerMapping和HandlerAdapter-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
2.2.4 视图页面(success.jsp)
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功页</title>
</head>
<body>
<h2>${hello}</h2>
</body>
</html>
2.2.5 Web 配置文件(web.xml)
xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置前端控制器DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 容器启动时加载Servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- /:处理所有请求(排除JSP);/*:处理所有请求(包含JSP) -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.3 测试

启动 Tomcat,访问http://localhost:8080/hello,页面显示欢迎你 springmvc!!即为成功。

2.4 SpringMVC 核心组件
- DispatcherServlet(前端控制器):流程控制中心,调用其他组件处理请求,降低耦合
- HandlerMapping(处理器映射器):根据请求 URL 查找对应的 Handler(处理器)
- Handler(处理器):自定义的 Controller,处理具体业务逻辑
- HandlerAdapter(处理器适配器):适配并执行 Handler(适配器模式)
- ViewResolver(视图解析器):将逻辑视图名解析为物理视图地址
- View(视图):渲染模型数据,将结果响应给浏览器
2.5 SpringMVC 执行流程

DispatcherServlet(前端控制器):接受请求,加载springmvc.xml
HandlerMapping(处理器映射器):查找handler
HandlerAdapter(处理器适配器):调用handler
ViewResolver(视图解析器):拼接jsp的路径
View(视图渲染器):把数据填充到request,跳转页面
- 用户发起请求到 DispatcherServlet
- DispatcherServlet 请求 HandlerMapping 查找 Handler
- HandlerMapping 返回 HandlerExecutionChain(包含 Handler + 拦截器)
- DispatcherServlet 调用 HandlerAdapter 执行 Handler
- HandlerAdapter 执行 Handler,返回 ModelAndView
- DispatcherServlet 请求 ViewResolver 解析视图
- ViewResolver 返回 View 对象
- DispatcherServlet 渲染视图(将 Model 数据填充到 View)
- DispatcherServlet 响应结果给用户
三、RequestMapping 注解
3.1 核心作用
建立请求 URL 和处理方法的映射关系(Map<url,方法>),可标注在类 / 方法上:
- 类上:定义请求 URL 的第一级目录(窄化路径)
- 方法上:建立url 和 方法 的映射关系
3.2 核心属性
value/path:指定请求 URLmethod:指定请求方式(RequestMethod.GET/POST 等)
3.3 实战示例
3.3.1 窄化路径
java
@Controller
@RequestMapping("/account") // 第一级目录
public class AccountController {
@RequestMapping("/findAccount") // 第二级目录
public ModelAndView findAccount() {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "欢迎你 springmvc");
mv.setViewName("success");
return mv;
}
}
index.jsp
html
<a href="/account/findAccount">窄化路径</a>
3.3.2 method属性指定请求方式
java
@Controller
@RequestMapping("/account")
public class AccountController {
// 仅允许POST请求
@RequestMapping(value = "/findAccount1", method = RequestMethod.POST)
public ModelAndView findAccount1() {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "欢迎你 springmvc");
mv.setViewName("success");
return mv;
}
}
POST 请求测试:
<form action="account/findAccount1" method="post">
<input type="submit" value="POST请求测试">
</form>
四、Controller 方法返回值
4.1 返回 ModelAndView
封装模型数据 + 视图名称,示例见 2.2.2。
4.2 返回字符串
4.2.1 逻辑视图名
java
@RequestMapping("/findAccount2")
public String findAccount2(Model model) {
model.addAttribute("msg", "返回字符串视图名");
return "success"; // 逻辑视图名,由视图解析器拼接路径
}
4.2.2 Redirect 重定向
java
@RequestMapping("/findAccount3")
public String findAccount3() {
// 重定向到另一个方法,浏览器地址栏变化,新请求
return "redirect:/account/findAccount4";
}
@RequestMapping("/findAccount4")
public String findAccount4(Model model) {
model.addAttribute("msg", "SpringMVC重定向");
return "success";
}
4.2.3 Forward 转发
java
@RequestMapping("/findAccount3")
public String findAccount3() {
// 转发到另一个方法,地址栏不变,共用请求
return "forward:/account/findAccount4";
}
五、请求参数接收
jsp--->参数--->controller
SpringMVC 通过方法形参接收参数,自动完成类型转换(特殊场景需自定义转换器)。
5.1 基本数据类型
java
@RequestMapping("/findAccount5")
public String findAccount5(String username, Integer age, Model model){
model.addAttribute("msg", username + " " + age);
return "success";
}
index.jsp
html
<a href="/account/findAccount5?username=eric&age=22">基本类型传参</a>
5.2 POJO 类型
5.2.1 定义 POJO
java
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
private Address address; // 嵌套POJO
// getter/setter/toString
}
public class Address implements Serializable {
private String provinceName;
private String cityName;
// getter/setter/toString
}
5.2.2 接收 POJO 参数
java
@RequestMapping("/saveAccount")
public String saveAccount(Account account, Model model){
model.addAttribute("msg", account);
return "success";
}
index.jsp
<form action="account/saveAccount" method="post">
账户名称:<input type="text" name="name"><br/>
账户金额:<input type="text" name="money"><br/>
省份:<input type="text" name="address.provinceName"><br/>
城市:<input type="text" name="address.cityName"><br/>
<input type="submit" value="保存">
</form>
5.3 RESTful 风格
5.3.1 核心思想
URL 定位资源,HTTP 动词描述操作:
- GET:查询(/user/1)
- POST:新增(/user)
- PUT:修改(/user)
- DELETE:删除(/user/1)
5.3.2 @PathVariable 注解
绑定 URL 占位符到方法形参:
java
@RequestMapping("/findAccount7/{id}")
public String findAccount7(@PathVariable Integer id, Model model){
model.addAttribute("msg", "RESTful传参:" + id);
return "success";
}
index.jsp
html
<a href="/account/findAccount7/123">RESTful传参</a>
5.4 解决参数乱码
5.4.1 POST 请求(编码过滤器)
在 web.xml 添加:
xml
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5.4.2 GET 请求(Tomcat 编码)
修改 pom.xml 的 Tomcat 插件:
xml
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding> <!-- GET请求编码 -->
</configuration>
</plugin>
5.5 自定义类型转换器
5.5.1 场景:日期类型转换
前端传递字符串日期(如 2024-01-01),后台用 Date 接收,需自定义转换器:
5.5.2 实现步骤
- 定义转换器类:
java
运行
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.parse(source);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- 配置转换器(springmvc.xml):
xml
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置类型转换器工厂 -->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.hg.converter.DateConverter"></bean>
</set>
</property>
</bean>
5.6 ServletAPI 接收参数
直接将 HttpServletRequest/HttpServletResponse 作为方法形参:
java
运行
@RequestMapping("/findAccount8")
public String findAccount8(HttpServletRequest request, HttpServletResponse response){
String username = request.getParameter("username");
String age = request.getParameter("age");
request.setAttribute("msg", username + " " + age);
return "success";
}
六、数据传递
6.1 ModelAndView 传递
java
运行
@RequestMapping("/findAccount9")
public ModelAndView findAccount9(ModelAndView mv) {
mv.addObject("msg", "ModelAndView传递数据");
mv.setViewName("success");
return mv;
}
6.2 Model 传递
java
运行
@RequestMapping("/findAccount10")
public String findAccount10(Model model) {
model.addAttribute("msg", "Model传递数据");
return "success";
}
6.3 ServletAPI 传递
java
运行
@RequestMapping("/findAccount11")
public String findAccount11(HttpServletRequest request){
request.setAttribute("msg", "ServletAPI传递数据");
return "success";
}
七、JSON 数据处理
7.1 添加依赖
SpringMVC 默认使用 Jackson 处理 JSON:
xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
7.2 核心注解
@RequestBody:接收前端 JSON 字符串,转为 Java 对象@ResponseBody:将 Java 对象转为 JSON 字符串,响应给前端
7.3 实战案例
7.3.1 后端 Controller
java
运行
@RequestMapping("/saveAccount2")
@ResponseBody // 响应JSON
public Map<String, Object> saveAccount2(@RequestBody Account account){
Map<String, Object> map = new HashMap<>();
map.put("status", 200);
map.put("msg", account);
return map;
}
7.3.2 前端 AJAX
html
预览
<input type="button" value="测试JSON交互" onClick="testJson()"/>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
function testJson(){
axios.post('/account/saveAccount2',{"id":1,"name":"张二狗","money":999.0})
.then(response => {
if(response.data.status === 200){
alert(response.data.msg.name);
}
})
.catch(error => console.error('请求失败:', error));
}
</script>
总结
本文从 SpringMVC 的核心概念出发,逐步讲解了环境搭建、入门案例、核心注解、参数接收、数据传递、JSON 交互等核心知识点。SpringMVC 作为轻量级 Web 框架,通过分层设计和注解化开发,大幅简化了控制层开发流程,是 Java Web 开发的必备技能。后续将继续讲解拦截器、文件上传、异常处理等高级特性,敬请关注!