Spring MVC 全面详解:原理、组件、实战与高级特性

目录

[一、Spring MVC 的核心定位与设计思想](#一、Spring MVC 的核心定位与设计思想)

[1. 什么是 MVC 设计模式?](#1. 什么是 MVC 设计模式?)

[2. Spring MVC 的核心思想:前端控制器模式](#2. Spring MVC 的核心思想:前端控制器模式)

[二、Spring MVC 的核心组件(职责与协作)](#二、Spring MVC 的核心组件(职责与协作))

[三、Spring MVC 的工作流程(核心执行链路)](#三、Spring MVC 的工作流程(核心执行链路))

[四、Spring MVC 的核心配置(注解驱动为主)](#四、Spring MVC 的核心配置(注解驱动为主))

[1. 环境准备(Maven 依赖)](#1. 环境准备(Maven 依赖))

[2. Java 核心配置类](#2. Java 核心配置类)

[(1)Web 容器初始化配置(替代 web.xml)](#(1)Web 容器初始化配置(替代 web.xml))

[(2)Spring MVC 配置类(WebConfig)](#(2)Spring MVC 配置类(WebConfig))

(3)根容器配置类(RootConfig)

五、核心注解与请求处理

[1. 控制器注解](#1. 控制器注解)

[2. 请求映射注解](#2. 请求映射注解)

示例:请求映射

[3. 请求参数绑定注解](#3. 请求参数绑定注解)

示例:参数绑定

六、数据模型与视图渲染

[1. 向视图传递数据](#1. 向视图传递数据)

[示例:Model 传递数据](#示例:Model 传递数据)

[Thymeleaf 视图渲染(user/list.html)](#Thymeleaf 视图渲染(user/list.html))

[2. RESTful 接口返回 JSON](#2. RESTful 接口返回 JSON)

[示例:返回 JSON](#示例:返回 JSON)

七、拦截器(HandlerInterceptor)

[1. 自定义拦截器](#1. 自定义拦截器)

[2. 注册拦截器(WebConfig 中配置)](#2. 注册拦截器(WebConfig 中配置))

八、异常处理

[1. 局部异常处理(@ExceptionHandler)](#1. 局部异常处理(@ExceptionHandler))

[2. 全局异常处理(@ControllerAdvice)](#2. 全局异常处理(@ControllerAdvice))

九、高级特性

[1. 跨域请求处理(CORS)](#1. 跨域请求处理(CORS))

[2. 文件上传](#2. 文件上传)

[3. 异步请求处理](#3. 异步请求处理)

[十、Spring MVC 的优势与应用场景](#十、Spring MVC 的优势与应用场景)

核心优势

应用场景

Spring MVC 是 Spring 框架的Web 模块,基于 MVC(Model-View-Controller)设计模式构建,用于快速开发灵活、松耦合的 Web 应用。它通过「前端控制器」统一处理请求,分离数据处理、页面展示和请求分发逻辑,是目前 Java 后端主流的 Web 开发框架之一。

一、Spring MVC 的核心定位与设计思想

1. 什么是 MVC 设计模式?

MVC 将应用分为三个核心角色,实现关注点分离:

  • Model(模型):封装业务数据和逻辑(如实体类、Service 层),专注数据处理;
  • View(视图):负责数据展示(如 JSP、Thymeleaf、Vue 页面),专注界面渲染;
  • Controller(控制器):接收用户请求,协调 Model 和 View(如调用 Service 获取数据,传递给 View 展示),专注请求分发。

2. Spring MVC 的核心思想:前端控制器模式

Spring MVC 通过DispatcherServlet(前端控制器) 统一接收所有请求,替代传统 MVC 中每个 Controller 独立处理请求的方式,实现「请求集中分发、组件解耦复用」。

简单说:DispatcherServlet 是整个 Spring MVC 的「中央调度器」,所有请求先经过它,再由它分发给对应的组件处理,最终返回响应。

二、Spring MVC 的核心组件(职责与协作)

Spring MVC 的核心组件围绕 DispatcherServlet 协同工作,每个组件各司其职:

三、Spring MVC 的工作流程(核心执行链路)

请求从客户端到服务器的完整处理流程,是理解 Spring MVC 的关键:

  1. 客户端发送请求 :如 http://localhost:8080/user/list,请求被 Tomcat 等 Servlet 容器接收;
  2. DispatcherServlet 接收请求:Servlet 容器将请求转发给 DispatcherServlet(配置的 URL 映射决定);
  3. HandlerMapping 匹配 Handler:DispatcherServlet 调用 HandlerMapping,根据请求 URL / 方法找到对应的 Controller 方法(Handler);
  4. HandlerAdapter 执行 Handler:DispatcherServlet 通过 HandlerAdapter 适配并执行 Handler,处理请求参数绑定、数据转换,调用 Service 层获取数据;
  5. Handler 返回 ModelAndView:Controller 方法执行完毕,返回 ModelAndView(或直接返回数据);
  6. ViewResolver 解析视图:DispatcherServlet 调用 ViewResolver,根据 ModelAndView 中的视图名称解析出实际 View;
  7. View 渲染响应:View 将 Model 数据渲染到页面(或直接返回 JSON 数据),生成响应;
  8. DispatcherServlet 返回响应:将渲染后的响应返回给客户端。

四、Spring MVC 的核心配置(注解驱动为主)

Spring MVC 支持XML 配置Java 配置,目前主流是 Java 配置(无 XML),以下是核心配置方式:

1. 环境准备(Maven 依赖)

XML 复制代码
<!-- Spring MVC 核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.20</version>
</dependency>
<!-- Servlet API(Tomcat 已提供,需标记为 provided) -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<!-- Thymeleaf 视图依赖(可选,替代 JSP) -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.12.RELEASE</version>
</dependency>

2. Java 核心配置类

(1)Web 容器初始化配置(替代 web.xml)

通过 AbstractAnnotationConfigDispatcherServletInitializer 配置 DispatcherServlet 和 Spring 容器:

java 复制代码
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

// Web 应用初始化器,替代 web.xml
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // 根容器配置类(Service、Dao 层)
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{RootConfig.class};
    }

    // Spring MVC 容器配置类(Controller、ViewResolver 等)
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    // DispatcherServlet 的 URL 映射("/" 表示处理所有请求)
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
(2)Spring MVC 配置类(WebConfig)
java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

@Configuration
@EnableWebMvc // 开启 Spring MVC 注解驱动(替代 XML 的 <mvc:annotation-driven>)
@ComponentScan("com.example.controller") // 扫描控制器包
public class WebConfig implements WebMvcConfigurer {

    // 配置 Thymeleaf 视图解析器
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(ServletContextTemplateResolver templateResolver) {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver);
        return engine;
    }

    @Bean
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/views/"); // 视图前缀(页面存放路径)
        resolver.setSuffix(".html"); // 视图后缀
        resolver.setTemplateMode("HTML5");
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }

    // 静态资源处理(如 CSS、JS、图片)
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**") // 访问路径
                .addResourceLocations("/WEB-INF/static/"); // 实际存放路径
    }
}
(3)根容器配置类(RootConfig)
java 复制代码
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(
    basePackages = "com.example",
    excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
)
// 扫描 Service、Dao 层,排除 Spring MVC 相关配置
public class RootConfig {
}

五、核心注解与请求处理

Spring MVC 通过注解简化请求映射和参数处理,以下是高频注解:

1. 控制器注解

  • @Controller:标注类为 Spring MVC 控制器,处理请求并返回视图;
  • @RestController@Controller + @ResponseBody 组合,返回 JSON/XML 数据(无需视图渲染),适用于 RESTful 接口。

2. 请求映射注解

  • @RequestMapping:映射请求 URL、方法(GET/POST)、参数等,可标注在类或方法上;
  • @GetMapping@RequestMapping(method = RequestMethod.GET) 的简写;
  • @PostMapping@RequestMapping(method = RequestMethod.POST) 的简写;
  • @PutMapping/@DeleteMapping:对应 PUT/DELETE 请求,支持 RESTful 风格。
示例:请求映射
java 复制代码
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping("/user") // 类级映射:所有方法URL前缀为 /user
public class UserController {

    // 匹配 GET /user/list
    @GetMapping("/list")
    public String userList() {
        return "user/list"; // 返回视图名称,ViewResolver 解析为 /WEB-INF/views/user/list.html
    }

    // 匹配 POST /user/add
    @PostMapping("/add")
    public String addUser() {
        return "redirect:/user/list"; // 重定向到列表页
    }

    // RESTful:匹配 GET /user/1(路径参数)
    @GetMapping("/{id}")
    @ResponseBody // 返回 JSON 数据
    public String getUserById(@PathVariable("id") Integer id) {
        return "User ID: " + id;
    }
}

3. 请求参数绑定注解

  • @RequestParam :绑定请求参数(如 ?name=张三);
  • @PathVariable :绑定 URL 路径参数(如 /user/{id});
  • @RequestBody:绑定请求体(JSON/XML 数据),适用于 POST/PUT 请求;
  • @RequestHeader:绑定请求头信息;
  • @CookieValue:绑定 Cookie 数据;
  • @ModelAttribute:绑定请求参数到实体对象(表单提交常用)。
示例:参数绑定
java 复制代码
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserRestController {

    // 绑定请求参数:/user/query?name=张三&age=20
    @GetMapping("/query")
    public String queryUser(
        @RequestParam("name") String name,
        @RequestParam(value = "age", defaultValue = "18") Integer age
    ) {
        return "Name: " + name + ", Age: " + age;
    }

    // 绑定路径参数:/user/123
    @GetMapping("/{id}")
    public String getUser(@PathVariable("id") Long id) {
        return "User ID: " + id;
    }

    // 绑定请求体(JSON):POST /user/save,Body {"name":"李四","age":25}
    @PostMapping("/save")
    public String saveUser(@RequestBody User user) {
        return "Saved: " + user.getName() + ", " + user.getAge();
    }

    // 表单提交绑定到实体:POST /user/form,FormData name=王五&age=30
    @PostMapping("/form")
    public String formSubmit(@ModelAttribute User user) {
        return "Form: " + user.getName();
    }
}

// User 实体类
class User {
    private String name;
    private Integer age;
    // getter/setter
}

六、数据模型与视图渲染

1. 向视图传递数据

Controller 可通过以下方式将数据传递给视图:

  • Model/ModelMap:添加数据到模型,视图可直接访问;
  • ModelAndView:同时封装视图名称和模型数据;
  • @SessionAttributes:将数据存入 Session(跨请求共享)。
示例:Model 传递数据
java 复制代码
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Arrays;
import java.util.List;

@Controller
@RequestMapping("/user")
public class UserController {

    @GetMapping("/list")
    public String userList(Model model) {
        // 模拟从 Service 获取用户列表
        List<User> userList = Arrays.asList(
            new User("张三", 20),
            new User("李四", 25)
        );
        // 添加数据到模型,视图中可通过 "users" 访问
        model.addAttribute("users", userList);
        model.addAttribute("title", "用户列表");
        return "user/list"; // 返回视图名称
    }
}
Thymeleaf 视图渲染(user/list.html)
html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${title}">用户列表</title>
</head>
<body>
    <h1 th:text="${title}">用户列表</h1>
    <table>
        <tr>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <tr th:each="user : ${users}">
            <td th:text="${user.name}">张三</td>
            <td th:text="${user.age}">20</td>
        </tr>
    </table>
</body>
</html>

2. RESTful 接口返回 JSON

使用 @RestController@ResponseBody,Spring MVC 会自动将对象序列化为 JSON(需引入 Jackson 依赖):

XML 复制代码
<!-- Jackson 依赖(JSON 序列化) -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.5</version>
</dependency>
示例:返回 JSON
java 复制代码
@RestController
@RequestMapping("/api/user")
public class UserApiController {

    @GetMapping("/{id}")
    public User getUser(@PathVariable("id") Long id) {
        return new User("张三", 20); // 自动序列化为 JSON:{"name":"张三","age":20}
    }
}

七、拦截器(HandlerInterceptor)

拦截器用于在请求处理的前、中、后 插入自定义逻辑(如登录验证、日志记录、权限检查),实现 HandlerInterceptor 接口:

1. 自定义拦截器

java 复制代码
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {

    // 请求处理前执行(返回 true 继续,false 终止)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查用户是否登录
        Object user = request.getSession().getAttribute("user");
        if (user == null) {
            // 未登录,重定向到登录页
            response.sendRedirect("/login");
            return false;
        }
        return true; // 已登录,继续处理请求
    }

    // 请求处理后、视图渲染前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可修改 ModelAndView 数据
    }

    // 视图渲染后执行(常用于资源清理)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 记录请求完成日志
    }
}

2. 注册拦截器(WebConfig 中配置)

java 复制代码
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {

    // 注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/user/**") // 拦截 /user 下所有请求
                .excludePathPatterns("/user/login"); // 排除登录请求
    }
}

八、异常处理

Spring MVC 提供多种异常处理方式,实现统一的异常响应:

1. 局部异常处理(@ExceptionHandler)

在 Controller 内定义,仅处理当前 Controller 的异常:

java 复制代码
@Controller
@RequestMapping("/user")
public class UserController {

    // 处理当前 Controller 的 RuntimeException
    @ExceptionHandler(RuntimeException.class)
    public String handleRuntimeException(RuntimeException e, Model model) {
        model.addAttribute("error", e.getMessage());
        return "error"; // 跳转到错误页面
    }
}

2. 全局异常处理(@ControllerAdvice)

全局生效,处理所有 Controller 的异常:

java 复制代码
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice // 全局控制器增强
public class GlobalExceptionHandler {

    // 处理所有 Exception
    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception e) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("error", "系统异常:" + e.getMessage());
        mav.setViewName("error"); // 错误页面
        return mav;
    }

    // 处理 REST 接口异常,返回 JSON
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public String handleIllegalArgument(IllegalArgumentException e) {
        return "{\"code\":400,\"msg\":\"" + e.getMessage() + "\"}";
    }
}

九、高级特性

1. 跨域请求处理(CORS)

通过 @CrossOrigin 或全局配置支持跨域:

java 复制代码
// 局部跨域(Controller/方法级)
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:8081") // 允许 8081 端口跨域
public class ApiController {
    // ...
}

// 全局跨域(WebConfig 中配置)
@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
            .allowedOrigins("http://localhost:8081")
            .allowedMethods("GET", "POST")
            .allowCredentials(true);
}

2. 文件上传

配置文件上传解析器,处理 multipart 请求:

java 复制代码
// WebConfig 中配置文件上传
@Bean
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setMaxUploadSize(10 * 1024 * 1024); // 最大上传大小 10MB
    resolver.setDefaultEncoding("UTF-8");
    return resolver;
}

// Controller 处理文件上传
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
    // 保存文件
    file.transferTo(new File("D:/uploads/" + file.getOriginalFilename()));
    return "redirect:/success";
}

3. 异步请求处理

支持异步响应(如处理耗时任务),避免线程阻塞:

java 复制代码
@RestController
@RequestMapping("/async")
public class AsyncController {

    @GetMapping("/task")
    public Callable<String> asyncTask() {
        return () -> {
            // 模拟耗时任务(5秒)
            Thread.sleep(5000);
            return "异步任务完成";
        };
    }
}

十、Spring MVC 的优势与应用场景

核心优势

  1. 松耦合设计:组件职责清晰,通过注解和接口解耦,易于扩展;
  2. 强大的配置灵活性:支持注解驱动、Java 配置、XML 配置,适配不同场景;
  3. 与 Spring 生态无缝集成:可直接使用 Spring 的 IoC、AOP、事务管理等功能;
  4. 全面的功能支持:覆盖请求处理、数据绑定、视图渲染、异常处理、拦截器等;
  5. RESTful 友好:原生支持 RESTful 风格的 URL 映射和 JSON 数据交互。

应用场景

  • 传统服务器渲染的 Web 应用(JSP/Thymeleaf);
  • RESTful API 接口开发(前后端分离项目);
  • 企业级 Web 应用(如电商、OA 系统);
  • 微服务架构中的 API 网关或服务接口。
相关推荐
wno70410 小时前
Spring Boot JdbcTemplate配置Druid多数据源
java·spring boot·后端
聊浮游10 小时前
JAVA2026最新全套学习资料、学习路线
java·开发语言·jvm·mysql·spring·maven·idea
MacroZheng11 小时前
完美替代 Navicat!这款内置 AI 的数据库工具,太香了!
java·后端·mysql
SamDeepThinking11 小时前
从REST到gRPC,一个API选型的思考框架
java·后端·程序员
Zane199411 小时前
接口都能写默认实现了,为什么还需要抽象类
java·后端
未秃头的程序猿11 小时前
读Spring AI源码的方法——不是硬啃,是带着问题去翻
java·后端·spring
用户31268748772011 小时前
别再 Thread.sleep 硬等了!并发工具类到底怎么选?
java
Java内核笔记11 小时前
万字长文剖析 Spring Boot 4 自动配置机制源码:从 @EnableAutoConfiguration 到条件装配
java·后端
evans在进步11 小时前
Spring MVC 核心机制详解:全局异常处理、请求跳转与数据绑定
java·spring·mvc
weixin_BYSJ198712 小时前
springboot小区物业管理小程序---附源码45555
java·javascript·spring boot·python·django·flask·php