目录
一、SpringMVC 的核心定位:为什么成为 Web 开发首选?
二、SpringMVC 的核心组件:各司其职的 “协作团队”
步骤 1:创建 Thymeleaf 模板(src/main/resources/templates/userDetail.html)
SpringMVC 框架深度解析:从核心原理到实战开发
SpringMVC 是 Spring 框架的 Web 模块核心,基于 MVC(Model-View-Controller)设计模式的轻量级 Java Web 开发框架。它与 Spring 框架无缝集成,无需额外整合配置,凭借 “松耦合、高扩展性、易用性” 的特点,成为企业级 Web 应用开发的首选框架(如电商平台、管理系统、RESTful API 服务等)。SpringMVC 不仅解决了传统 JSP+Servlet 开发的代码冗余、耦合度高的问题,还提供了请求处理、参数绑定、视图渲染、异常处理等一站式 Web 开发解决方案。本文将从核心定位、核心组件、工作流程、实战开发到进阶技巧,帮助你全面掌握 SpringMVC 框架。
一、SpringMVC 的核心定位:为什么成为 Web 开发首选?
在传统 Java Web 开发中,Servlet 负责接收请求、处理业务,JSP 负责视图渲染,但存在明显弊端:Servlet 配置繁琐、参数解析复杂、视图与业务逻辑耦合度高、异常处理分散。SpringMVC 的出现彻底解决了这些问题,其核心定位是 “基于 MVC 模式的 Web 层解决方案,简化 Web 开发,实现业务逻辑与视图展示的解耦”。
SpringMVC 的核心优势体现在 5 点:
- 无缝集成 Spring 生态:与 Spring Core、Spring AOP、Spring Transaction 等模块天然整合,无需额外适配,可直接使用 Spring 的依赖注入、事务管理等特性;
- 强大的请求处理能力:支持 RESTful 风格 URL、多种请求方式(GET/POST/PUT/DELETE)、参数自动绑定(基本类型、对象、集合、文件上传);
- 灵活的视图机制:支持 JSP、Thymeleaf、Freemarker 等多种视图技术,也可直接返回 JSON/XML 数据(无需视图渲染);
- 完善的扩展机制:支持拦截器、异常处理器、类型转换器等自定义扩展,满足复杂业务需求;
- 低侵入性:无需继承特定父类或实现特定接口(仅需注解声明),保持代码纯粹性,学习成本低。
如今,SpringMVC 已成为 Java Web 开发的 “标准框架”,无论是单体应用还是微服务架构(如 Spring Cloud),都能提供高效、灵活的 Web 层支持。
二、SpringMVC 的核心组件:各司其职的 “协作团队”
SpringMVC 的核心是一套组件协作机制,每个组件承担特定职责,共同完成 “请求接收→业务处理→响应返回” 的全流程。以下是最核心的组件及作用:
| 组件名称 | 核心作用 |
|---|---|
| DispatcherServlet(前端控制器) | SpringMVC 的 “中枢神经”,接收所有客户端请求,分发到对应组件处理,是请求的统一入口; |
| HandlerMapping(处理器映射器) | 根据请求 URL 和配置(注解 / XML),找到对应的 Handler(处理器,如 Controller 方法),并返回 HandlerExecutionChain(包含 Handler 和拦截器); |
| HandlerAdapter(处理器适配器) | 适配不同类型的 Handler(如注解式 Controller、XML 配置的 Controller),调用 Handler 的业务方法,屏蔽不同 Handler 的调用差异; |
| Handler(处理器) | 实际处理请求的业务组件,通常是带有@Controller注解的类中的方法(即 “控制器方法”); |
| ModelAndView(模型视图) | 封装处理结果:Model存储业务数据(键值对),View指定视图名称(如 “index”),用于视图渲染; |
| ViewResolver(视图解析器) | 根据 View 名称,解析出实际的视图对象(如 JSP 路径、Thymeleaf 模板),并将 Model 中的数据渲染到视图; |
| HandlerInterceptor(拦截器) | 拦截请求处理流程(如请求前验证权限、请求后记录日志),可自定义扩展,类似 Spring AOP 的横切逻辑; |
| ExceptionResolver(异常处理器) | 统一处理请求过程中抛出的异常,避免异常直接暴露给客户端,提供友好的错误响应; |
核心组件的协作关系:DispatcherServlet 作为 “总指挥”,协调 HandlerMapping、HandlerAdapter、ViewResolver 等组件,无需开发者手动干预组件交互,只需关注业务逻辑实现。
三、SpringMVC 的工作流程:从请求到响应的完整链路
SpringMVC 的工作流程本质是 “组件协作的顺序化执行”,从客户端发送请求到响应返回,共分为 10 个核心步骤,流程清晰且易于理解:

步骤详解(结合实际场景):
- 客户端发送请求:用户访问
http://localhost:8080/user/1(GET 请求,查询 ID 为 1 的用户); - DispatcherServlet 接收请求:Tomcat 将请求转发给 SpringMVC 的 DispatcherServlet(web.xml 或 JavaConfig 中配置的核心 Servlet);
- HandlerMapping 查找 Handler:HandlerMapping 根据 URL
/user/1和@GetMapping注解,找到对应的 Controller 方法(如UserController.getUserById(1)); - 返回 HandlerExecutionChain:包含找到的 Handler(Controller 方法)和配置的拦截器(如权限拦截器);
- HandlerAdapter 适配调用:HandlerAdapter 根据 Handler 的类型(注解式 Controller),自动解析请求参数(如路径参数
1绑定到userId),调用 Controller 方法; - Handler 处理业务:Controller 方法调用 Service 层查询用户数据,返回
ModelAndView(如new ModelAndView("userDetail", "user", user),视图名称为userDetail,模型数据为user对象); - ViewResolver 解析视图:ViewResolver 根据视图名称
userDetail,解析出实际视图路径(如 Thymeleaf 模板classpath:templates/userDetail.html); - 视图渲染:将 Model 中的
user数据注入到视图模板中,生成最终的 HTML 页面; - 返回响应:DispatcherServlet 将渲染后的 HTML 页面返回给客户端,用户看到查询结果。
特殊场景:无视图响应(返回 JSON)
若 Controller 方法添加@ResponseBody注解(或类上添加@RestController),则无需视图渲染,直接将返回的对象(如 User、List)序列化为 JSON 数据响应给客户端,流程简化为:Handler处理业务 → 返回Java对象 → DispatcherServlet将对象序列化为JSON → 返回响应。
四、SpringMVC 实战开发:从环境搭建到接口实现
下面通过 “用户管理模块” 实战,演示 SpringMVC 的核心用法,包含环境搭建、请求处理、参数绑定、视图渲染、异常处理等核心功能。
1. 环境搭建(基于 Spring Boot,简化配置)
Spring Boot 已内置 SpringMVC 自动配置,无需手动配置 DispatcherServlet、ViewResolver 等组件,只需引入依赖即可:
步骤 1:添加 Maven 依赖(pom.xml)
org.springframework.boot
spring-boot-starter-web
2.7.15
org.springframework.boot
spring-boot-starter-thymeleaf
2.7.15
步骤 2:启动类配置(Spring Boot 入口)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// @SpringBootApplication包含@ComponentScan,自动扫描当前包及子包的注解组件
@SpringBootApplication
public class SpringMvcDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMvcDemoApplication.class, args);
}
}
2. 核心实战 1:请求映射与参数绑定
SpringMVC 支持多种请求方式和参数绑定场景,以下是最常用的用法:
(1)RESTful 风格 URL 与路径参数
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// 声明为Controller组件,处理请求
@Controller
// 父路径:/user,所有子路径都以/user开头
@RequestMapping("/user")
public class UserController {
// 匹配GET请求:/user/{userId},{userId}为路径参数
@GetMapping("/{userId}")
public String getUserById(@PathVariable Integer userId, Model model) {
// 模拟Service层查询用户(实际开发中注入UserService)
User user = new User(userId, "张三", 25);
// 将用户数据存入Model,供视图使用(键为"user",值为user对象)
model.addAttribute("user", user);
// 返回视图名称:userDetail(对应Thymeleaf模板userDetail.html)
return "userDetail";
}
}
// 实体类
class User {
private Integer id;
private String name;
private Integer age;
// 构造器、Getter、Setter
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// Getter、Setter省略
}
(2)请求参数绑定(基本类型、对象、集合)
import org.springframework.web.bind.annotation.*;
import java.util.List;
// @RestController = @Controller + @ResponseBody,所有方法直接返回JSON
@RestController
@RequestMapping("/user")
public class UserRestController {
// 1. 基本类型参数:匹配GET请求:/user/query?name=张三&age=25
@GetMapping("/query")
public User queryUser(String name, Integer age) {
return new User(null, name, age);
}
// 2. 对象参数:匹配POST请求,接收JSON格式参数(如{"name":"李四","age":30})
@PostMapping
public String addUser(@RequestBody User user) {
// 模拟保存用户
return "新增用户成功:" + user.getName();
}
// 3. 集合参数:匹配PUT请求,接收JSON数组(如[{"id":1},{"id":2}])
@PutMapping("/batch")
public String updateBatch(@RequestBody List userList) {
return "批量更新" + userList.size() + "个用户";
}
}
(3)文件上传
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@RestController
public class FileUploadController {
// 接收文件上传请求,参数名需与前端表单name一致(如"file")
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
// 检查文件是否为空
if (file.isEmpty()) {
return "文件不能为空";
}
// 保存文件到本地(实际开发中建议存入OSS等云存储)
String filePath = "D:/upload/" + file.getOriginalFilename();
file.transferTo(new File(filePath));
return "文件上传成功,路径:" + filePath;
}
}
3. 核心实战 2:视图渲染(Thymeleaf 示例)
SpringMVC 支持多种视图技术,这里以 Thymeleaf(现代模板引擎,替代 JSP)为例,演示视图渲染:
步骤 1:创建 Thymeleaf 模板(src/main/resources/templates/userDetail.html)
用户详情
用户详情页
用户ID:
用户名:
年龄:
步骤 2:访问效果
启动应用后,访问http://localhost:8080/user/1,页面会渲染出:
用户详情页
用户ID:1
用户名:张三
年龄:25
4. 核心实战 3:拦截器(Interceptor)
拦截器用于拦截请求处理流程,可实现权限验证、日志记录、耗时统计等功能。自定义拦截器需实现HandlerInterceptor接口:
步骤 1:自定义拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 日志拦截器:记录请求URL和耗时
public class LogInterceptor implements HandlerInterceptor {
private long startTime;
// 请求处理前执行(如权限验证)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
startTime = System.currentTimeMillis();
String url = request.getRequestURL().toString();
System.out.printf("[拦截器] 接收请求:%s,请求方式:%s%n", url, request.getMethod());
// 返回true:放行请求;返回false:拦截请求(不执行后续Handler)
return true;
}
// 视图渲染后执行(如记录日志)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long costTime = System.currentTimeMillis() - startTime;
System.out.printf("[拦截器] 请求处理完成,耗时:%dms%n", costTime);
}
}
步骤 2:注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
// SpringMVC配置类,实现WebMvcConfigurer接口自定义配置
@Configuration
public class MvcConfig implements WebMvcConfigurer {
// 注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/static/**"); // 排除静态资源(如CSS、JS)
}
}
执行效果
访问http://localhost:8080/user/1时,控制台输出:
[拦截器] 接收请求:http://localhost:8080/user/1,请求方式:GET
[拦截器] 请求处理完成,耗时:10ms
5. 核心实战 4:全局异常处理
SpringMVC 提供@ControllerAdvice注解,可实现全局异常处理,避免异常直接暴露给客户端:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
// 全局异常处理器:处理所有Controller抛出的异常
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理空指针异常
@ExceptionHandler(NullPointerException.class)
public ResponseEntity handleNullPointerException(NullPointerException e) {
// 返回HTTP状态码400(Bad Request)和错误信息
return new ResponseEntity<>("请求参数错误:" + e.getMessage(), HttpStatus.BAD_REQUEST);
}
// 处理通用异常(所有未明确处理的异常)
@ExceptionHandler(Exception.class)
public ResponseEntity handleException(Exception e) {
// 返回HTTP状态码500(Internal Server Error)和错误信息
return new ResponseEntity<>("服务器内部错误:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
五、SpringMVC 进阶技巧:优化与扩展
1. 类型转换器(Converter)
SpringMVC 默认支持基本类型与字符串的转换(如String转Integer),若需自定义转换规则(如String转Date),可实现Converter接口:
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
// 自定义转换器:String -> Date(支持"yyyy-MM-dd"格式)
@Component
public class StringToDateConverter implements Converter {
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date convert(String source) {
try {
return sdf.parse(source);
} catch (ParseException e) {
throw new IllegalArgumentException("日期格式错误,需为yyyy-MM-dd");
}
}
}
使用时,Controller 方法可直接接收Date类型参数:
@GetMapping("/date")
public String getDate(Date date) {
return "日期:" + date;
}
访问http://localhost:8080/date?date=2024-01-01,会自动转换为Date对象。
2. 静态资源配置
SpringMVC 默认将src/main/resources/static目录作为静态资源(CSS、JS、图片)的存放路径,无需额外配置即可访问。例如:
- 静态资源路径:
src/main/resources/static/css/style.css - 访问 URL:
http://localhost:8080/css/style.css
若需自定义静态资源路径,可在MvcConfig中配置:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 配置"/img/**"映射到classpath:/images/目录
registry.addResourceHandler("/img/**")
.addResourceLocations("classpath:/images/");
}
3. 跨域配置(CORS)
前后端分离项目中,前端(如 Vue、React)与后端(SpringMVC)可能存在跨域问题,可通过@CrossOrigin注解或全局配置解决:
方式 1:局部跨域(单个 Controller / 方法)
// 允许所有域名跨域访问该Controller
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/user")
public class UserRestController {
// ...
}
方式 2:全局跨域(所有 Controller)
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 所有请求
.allowedOrigins("*") // 允许所有域名
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方式
.allowedHeaders("*") // 允许的请求头
.maxAge(3600); // 预检请求缓存时间(1小时)
}
六、总结
SpringMVC 框架以 “前端控制器(DispatcherServlet)为核心,组件协作为机制”,实现了 Web 开发的解耦与简化。其核心价值在于:通过 MVC 模式分离业务逻辑与视图展示,通过强大的组件支持请求处理、参数绑定、视图渲染等全流程,通过无缝集成 Spring 生态提供丰富的扩展能力。
掌握 SpringMVC 的关键在于:
- 理解核心组件的职责与协作关系,明确请求处理的完整流程;
- 熟练使用注解(
@Controller、@RequestMapping、@ResponseBody等)实现请求处理与参数绑定; - 掌握拦截器、异常处理器、类型转换器等扩展机制,满足复杂业务需求;
- 结合 Spring Boot 的自动配置,简化框架搭建与配置。
无论是传统的服务端渲染项目(JSP/Thymeleaf),还是前后端分离的 RESTful API 项目,SpringMVC 都能提供高效、灵活的解决方案。作为 Java 后端开发者,掌握 SpringMVC 是从事 Web 开发的必备技能,也是深入学习 Spring 生态(如 Spring Cloud)的基础。
浙公网安备 33010602011771号