前言
在 Java EE 开发中,Servlet 作为传统的控制层实现方式存在诸多缺陷,而 SpringMVC 作为 Spring 框架的核心模块之一,是基于 MVC 设计模式的轻量级 Web 开发框架,现已成为企业级项目表述层开发的首选方案。本文将从 SpringMVC 概述、环境搭建、核心注解、参数处理、数据传递到 JSON 交互,全方位讲解 SpringMVC 入门核心知识点。
一、SpringMVC 概述
1.1 为什么选择 SpringMVC?
先看传统 Servlet 的实现案例:
java
@WebServlet("/addUser")
public class AddUserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
// 手动接收所有参数,繁琐且易出错
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 的核心缺陷:
- 一个 Servlet 实例只能处理一个请求,导致类爆炸
- 参数接收需手动解析,类型转换繁琐(如 String 转 Integer)
- 代码耦合度高,不利于维护和扩展
1.2 MVC 设计模式
MVC 将软件分为三层,各司其职:
| 层级 | 说明 | 具体实现 |
|---|---|---|
| Model(模型层) | 处理数据 | 数据承载 Bean(User/Student)、业务处理 Bean(Service/Dao) |
| View(视图层) | 交互展示 | HTML/JSP 页面 |
| Controller(控制层) | 接收请求 / 响应浏览器 | Servlet/SpringMVC 的 Controller |
MVC 工作流程:用户通过视图层发送请求 → 控制器接收请求 → 调用模型层处理数据 → 模型层返回结果给控制器 → 控制器渲染视图 → 响应给浏览器
1.3 SpringMVC 核心定位
- SpringMVC 本质上等价于 Servlet,是 Spring 为控制层提供的完整解决方案
- 对比 Struts2 等框架,SpringMVC 具有轻量、高效、易整合 Spring 生态的优势
- 是当前 Java EE 项目表述层开发的首选框架
二、SpringMVC 入门环境搭建
2.1 工程创建(IDEA)
- 创建 Maven 工程,选择
maven-archetype-webapp(或普通 Maven 工程后添加 Web 支持) - 右键项目 →
Add Framework Support→ 勾选Web Application - 将生成的
web目录拖拽到main下,并重命名为webapp(关键!)
2.2 核心依赖(pom.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>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- SpringMVC核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- Servlet依赖(仅编译时有效) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!-- Tomcat插件配置 -->
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<!-- 解决GET请求中文乱码 -->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3 入门案例核心代码
(1)前端页面(index.jsp)
XML
<%@ 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)控制器(HelloController.java)
java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
// 交给Spring容器管理
@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;
}
}
(3)SpringMVC 配置文件(springmvc.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">
<!-- 扫描指定包下的注解(如@Controller) -->
<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>
(4)视图页面(success.jsp)
XML
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功页</title>
</head>
<body>
<h2>${hello}</h2>
</body>
</html>
(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">
<!-- 配置SpringMVC前端控制器 -->
<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(优先级1) -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 映射所有请求(/ 不包含.jsp,/* 包含所有) -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 解决POST请求中文乱码过滤器 -->
<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>
</web-app>
2.4 测试访问
启动 Tomcat,访问http://localhost:8080/hello,页面显示欢迎你 springmvc!!即为成功。
三、SpringMVC 核心组件与执行流程
3.1 核心组件
| 组件 | 核心作用 |
|---|---|
| DispatcherServlet(前端控制器) | 流程控制中心,协调所有组件 |
| HandlerMapping(处理器映射器) | 根据请求 URL 查找对应的 Handler |
| HandlerAdapter(处理器适配器) | 适配并执行 Handler(适配器模式) |
| ViewResolver(视图解析器) | 将逻辑视图名解析为物理视图地址 |
| View(视图) | 渲染模型数据,响应浏览器 |
3.2 完整执行流程
- 用户发起请求到 DispatcherServlet
- DispatcherServlet 请求 HandlerMapping 查找 Handler
- HandlerMapping 返回 HandlerExecutionChain(包含 Handler + 拦截器)
- DispatcherServlet 通过 HandlerAdapter 执行 Handler
- Handler 执行完成返回 ModelAndView
- DispatcherServlet 请求 ViewResolver 解析视图
- ViewResolver 返回 View 对象
- DispatcherServlet 渲染 View(将 Model 数据放入 request)
- DispatcherServlet 响应结果给用户
四、RequestMapping 注解详解
4.1 核心作用
建立请求 URL 与控制器方法的映射关系,可作用于类 或方法。
4.2 窄化路径(类级别)
java
@Controller
@RequestMapping("/account") // 第一级路径
public class AccountController {
@RequestMapping("/findAccount") // 第二级路径
public ModelAndView findAccount() {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "窄化路径测试");
mv.setViewName("success");
return mv;
}
}
访问路径:http://localhost:8080/account/findAccount
4.3 指定请求方式(method 属性)
java
@RequestMapping(value = "/findAccount1", method = RequestMethod.POST)
public ModelAndView findAccount1() {
ModelAndView mv = new ModelAndView();
mv.addObject("msg", "POST请求测试");
mv.setViewName("success");
return mv;
}
- 仅允许 POST 请求访问,GET 请求会返回 405 错误
- 可同时指定多个请求方式:
method = {RequestMethod.GET, RequestMethod.POST}
五、Controller 方法返回值类型
5.1 返回 ModelAndView
最基础方式,封装模型数据和视图名(如入门案例)。
5.2 返回字符串
(1)逻辑视图名
java
@RequestMapping("/findAccount2")
public String findAccount2(Model model) {
model.addAttribute("msg", "返回字符串视图名");
return "success"; // 逻辑视图名,由视图解析器拼接路径
}
(2)重定向(Redirect)
java
@RequestMapping("/findAccount3")
public String findAccount3() {
// 重定向到另一个方法(浏览器地址栏变化,新请求)
return "redirect:/account/findAccount4";
}
@RequestMapping("/findAccount4")
public String findAccount4(Model model) {
model.addAttribute("msg", "重定向测试");
return "success";
}
(3)转发(Forward)
java
@RequestMapping("/findAccount3")
public String findAccount3() {
// 转发到另一个方法(地址栏不变,共用request)
return "forward:/account/findAccount4";
}
六、参数接收全攻略
6.1 基本数据类型
java
@RequestMapping("/findAccount5")
public String findAccount5(String username, Integer age, Model model) {
model.addAttribute("msg", "用户名:" + username + ",年龄:" + age);
return "success";
}
访问路径:http://localhost:8080/account/findAccount5?username=eric&age=22
6.2 POJO 类型参数绑定
(1)定义 POJO
java
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
private String pwd;
private String address;
// getter/setter/toString
}
(2)接收参数
java
@RequestMapping("/saveAccount")
public String saveAccount(Account account, Model model) {
model.addAttribute("msg", account.toString());
return "success";
}
(3)前端表单
html
<form action="account/saveAccount" method="post">
账户名称:<input type="text" name="name"><br/>
账户金额:<input type="text" name="money"><br/>
账户密码:<input type="text" name="pwd"><br/>
账户地址:<input type="text" name="address"><br/>
<input type="submit" value="保存">
</form>
6.3 RESTful 风格传参(@PathVariable)
(1)RESTful 核心思想
URL 定位资源,HTTP 动词(GET/POST/PUT/DELETE)描述操作:
| 传统 URL | RESTful URL | 请求方式 | 操作 |
|---|---|---|---|
| /user/query?id=1 | /user/1 | GET | 查询 |
| /user/save | /user | POST | 新增 |
| /user/update | /user | PUT | 修改 |
| /user/delete?id=1 | /user/1 | DELETE | 删除 |
(2)代码实现
java
@RequestMapping("/findAccount7/{id}")
public String findAccount7(@PathVariable Integer id, Model model) {
model.addAttribute("msg", "RESTful传参:" + id);
return "success";
}
访问路径:http://localhost:8080/account/findAccount7/123