跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

SpringMVC 核心原理与实战应用详解

系统讲解 SpringMVC 框架,涵盖 MVC 设计模式、核心组件(DispatcherServlet、HandlerMapping 等)及执行流程。内容包括基于 Spring Boot 的环境搭建、请求参数绑定、视图解析(Thymeleaf)、拦截器、异常处理、文件上传等实战技巧,以及 SpringMVC 与 MyBatis 的集成方案,帮助开发者掌握 Web 层开发核心技术。

虚拟内存发布于 2026/3/30更新于 2026/7/1941 浏览
SpringMVC 核心原理与实战应用详解

前言

在 Java EE 企业级开发领域,SpringMVC 作为轻量级的 Web 层开发框架,凭借其清晰的架构设计、灵活的配置方式以及与 Spring 生态的无缝集成,成为了当前主流的 Web 开发技术选型之一。它基于 MVC(Model-View-Controller)设计模式,通过分离模型、视图和控制器的职责,有效降低了代码耦合度,提升了项目的可维护性和扩展性。本文将从 SpringMVC 的基础概念出发,逐步深入其核心原理、核心组件、实战应用、高级特性等关键知识点,结合理论讲解与代码示例,帮助读者系统掌握 SpringMVC 技术栈。

一、SpringMVC 概述

1.1 MVC 设计模式简介

MVC(Model-View-Controller)是一种经典的软件架构设计模式,其核心思想是将应用程序的功能划分为三个独立的模块,通过明确的职责划分实现代码解耦。

  • Model(模型):负责封装应用程序的核心数据和业务逻辑,是应用程序的数据层和业务层的结合体。模型不依赖于视图和控制器,仅专注于数据的处理和业务规则的实现。常见的模型组件包括实体类(Entity)、服务类(Service)、数据访问类(DAO)等。
  • View(视图):负责向用户展示数据,是用户与应用程序交互的界面。视图仅负责数据的呈现,不涉及业务逻辑的处理。常见的视图技术包括 JSP、Thymeleaf、Freemarker 等。
  • Controller(控制器):负责接收用户的请求,协调模型和视图完成用户需求。控制器接收请求后,调用模型进行业务逻辑处理,获取处理结果后,选择合适的视图向用户展示数据。

MVC 设计模式的优势在于实现了功能模块的分离,使得代码结构清晰,便于团队协作开发和后期维护。当需求发生变化时,只需修改对应的模块,不会影响其他模块的功能。

1.2 SpringMVC 的定义与核心优势

SpringMVC 是 Spring 框架的一个重要模块,是基于 Java 实现 MVC 设计模式的轻量级 Web 框架。它并非对 MVC 设计模式的全新实现,而是在 Spring 生态的基础上,对 MVC 架构进行了优化和封装,提供了一套简洁、高效的 Web 开发解决方案。

SpringMVC 的核心优势主要体现在以下几个方面:

  • 与 Spring 无缝集成:SpringMVC 是 Spring 框架的一部分,能够直接使用 Spring 的 IOC 容器、AOP 等核心特性,无需额外的整合配置,降低了框架集成的复杂度。
  • 灵活的配置方式:支持 XML 配置和注解配置两种方式,注解配置简化了开发流程,提高了开发效率;XML 配置则便于对全局配置进行统一管理,适用于复杂的项目场景。
  • 清晰的架构设计:基于 MVC 设计模式,职责划分明确,各组件之间耦合度低,便于代码的维护和扩展。
  • 强大的功能支持:提供了请求参数绑定、数据验证、视图解析、异常处理、文件上传等一系列完善的功能,满足企业级 Web 开发的各种需求。
  • 良好的扩展性:支持自定义拦截器、转换器、格式化器等组件,能够根据项目的特殊需求进行功能扩展。

1.3 SpringMVC 的应用场景

SpringMVC 适用于各种规模的 Java Web 项目开发,尤其是企业级应用项目。无论是中小型的管理系统、电商平台,还是大型的分布式 Web 应用,SpringMVC 都能凭借其灵活的架构和强大的功能满足开发需求。此外,由于 SpringMVC 与 Spring Boot、Spring Cloud 等主流技术的无缝集成,它也成为了微服务架构中 Web 层开发的首选技术。

二、SpringMVC 核心原理与执行流程

2.1 SpringMVC 核心组件

SpringMVC 的核心功能是通过一系列组件协同工作实现的,每个组件都有明确的职责。了解这些核心组件是掌握 SpringMVC 原理的关键。

2.1.1 前端控制器(DispatcherServlet)

DispatcherServlet 是 SpringMVC 的核心控制器,负责接收所有用户的请求,并协调其他组件完成请求的处理。它是整个 SpringMVC 流程的入口,相当于一个'中央处理器'。DispatcherServlet 的主要职责包括:

  • 接收 HTTP 请求,解析请求 URL 和请求参数;
  • 根据请求信息查找对应的处理器(Handler);
  • 调用处理器适配器(HandlerAdapter)执行处理器;
  • 接收处理器的处理结果(ModelAndView);
  • 调用视图解析器(ViewResolver)解析视图,渲染并返回响应结果。
2.1.2 处理器映射器(HandlerMapping)

HandlerMapping 的职责是根据用户请求的 URL,查找对应的处理器(Handler)和拦截器(Interceptor)。SpringMVC 提供了多种 HandlerMapping 实现,例如:

  • RequestMappingHandlerMapping:支持@RequestMapping 注解的处理器映射,是当前最常用的映射器;
  • BeanNameUrlHandlerMapping:根据 Bean 的名称作为 URL 进行映射;
  • SimpleUrlHandlerMapping:通过 XML 配置的方式,将 URL 与处理器进行直接映射。

当 DispatcherServlet 接收到请求后,会调用 HandlerMapping 获取对应的 HandlerExecutionChain(包含处理器和拦截器)。

2.1.3 处理器适配器(HandlerAdapter)

HandlerAdapter 的职责是适配不同类型的处理器,使得 DispatcherServlet 无需关心处理器的具体实现,能够统一调用处理器的处理方法。由于 SpringMVC 支持多种类型的处理器(如注解式处理器、控制器接口实现类等),不同处理器的调用方式不同,HandlerAdapter 通过适配模式解决了这一问题。

常用的 HandlerAdapter 实现包括:

  • RequestMappingHandlerAdapter:适配使用@RequestMapping 注解的处理器;
  • SimpleControllerHandlerAdapter:适配实现 Controller 接口的处理器;
  • SimpleServletHandlerAdapter:适配实现 Servlet 接口的处理器。
2.1.4 处理器(Handler)

Handler 即业务处理器,是 SpringMVC 中处理具体业务逻辑的组件,相当于 MVC 架构中的 Controller。处理器接收请求参数,调用业务层服务完成数据处理,最终返回处理结果(ModelAndView)。在实际开发中,处理器通常是一个使用@RequestMapping 注解的 Controller 类中的方法。

2.1.5 视图解析器(ViewResolver)

ViewResolver 的职责是根据处理器返回的 ModelAndView 中的视图名称,解析出具体的视图对象(View)。它将逻辑视图名转换为物理视图路径,例如将'index'解析为'/WEB-INF/views/index.jsp'。

常用的 ViewResolver 实现包括:

  • InternalResourceViewResolver:解析 JSP 视图,是最常用的视图解析器;
  • ThymeleafViewResolver:解析 Thymeleaf 视图;
  • FreeMarkerViewResolver:解析 Freemarker 视图。
2.1.6 视图(View)

View 是视图组件,负责将处理器返回的数据(Model)渲染为用户可查看的界面。View 接收 Model 中的数据,通过特定的视图技术(如 JSP、Thymeleaf)将数据展示出来。不同的视图技术对应不同的 View 实现类。

2.1.7 模型和视图(ModelAndView)

ModelAndView 是处理器返回的结果对象,包含了视图名称和需要展示的数据(Model)。其中,Model 是一个键值对集合,用于存储需要传递给视图的数据;ViewName 是逻辑视图名,用于视图解析器解析具体的视图。

2.2 SpringMVC 执行流程详解

SpringMVC 的请求处理流程是一个标准化的流程,各组件按照固定的顺序协同工作。以下是 SpringMVC 完整的执行流程,结合核心组件的交互进行说明:

  1. 用户发送 HTTP 请求:用户通过浏览器向服务器发送请求,请求 URL 例如'http://localhost:8080/springmvc/user/list'。
  2. 请求到达前端控制器(DispatcherServlet):服务器接收到请求后,根据 Web.xml 中的配置(或 Spring Boot 的自动配置),将请求转发给 DispatcherServlet。DispatcherServlet 是 SpringMVC 的入口,负责统一处理所有请求。
  3. DispatcherServlet 调用处理器映射器(HandlerMapping):DispatcherServlet 将请求 URL 传递给 HandlerMapping,HandlerMapping 根据 URL 查找对应的处理器(Handler)和拦截器(Interceptor),返回 HandlerExecutionChain 对象(包含处理器和拦截器列表)。
  4. DispatcherServlet 调用处理器适配器(HandlerAdapter):DispatcherServlet 根据 HandlerMapping 返回的处理器类型,选择对应的 HandlerAdapter。HandlerAdapter 负责适配处理器,调用处理器的处理方法(如 Controller 中的@RequestMapping 注解方法)。
  5. 处理器执行业务逻辑并返回 ModelAndView:处理器(Controller 方法)接收请求参数,调用业务层(Service)的方法完成数据处理,将处理结果(数据)存入 Model,设置逻辑视图名,最终返回 ModelAndView 对象。
  6. DispatcherServlet 调用视图解析器(ViewResolver):DispatcherServlet 将 ModelAndView 中的逻辑视图名传递给 ViewResolver,ViewResolver 解析出具体的物理视图路径(如'/WEB-INF/views/user/list.jsp'),返回 View 对象。
  7. 视图渲染数据:View 对象接收 Model 中的数据,通过视图技术(如 JSP)将数据渲染为 HTML 页面。
  8. 返回响应结果:渲染后的 HTML 页面通过 HTTP 响应返回给用户浏览器,用户看到最终的页面效果。

注意:在整个执行流程中,拦截器会在处理器执行前后进行拦截处理,实现权限控制、日志记录等功能。拦截器的执行顺序是:preHandle(处理器执行前)→ 处理器执行 → postHandle(处理器执行后,视图渲染前)→ afterCompletion(视图渲染后)。

三、SpringMVC 入门实战

3.1 环境搭建(基于 Spring Boot)

Spring Boot 提供了自动配置功能,能够快速搭建 SpringMVC 项目,无需繁琐的 XML 配置。以下是基于 Spring Boot 的 SpringMVC 环境搭建步骤:

3.1.1 创建 Maven 项目

使用 IDEA 或 Eclipse 创建一个 Maven 项目,选择'Spring Initializr'模板(IDEA 内置),填写项目基本信息(Group、Artifact、Version 等)。

3.1.2 引入依赖

在 pom.xml 文件中引入 Spring Boot Web 依赖(包含 SpringMVC 核心依赖):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot Starter Web 依赖会自动引入 SpringMVC 的核心组件(DispatcherServlet、HandlerMapping、ViewResolver 等)以及 Tomcat 服务器依赖,实现开箱即用。

3.1.3 编写主启动类

创建 Spring Boot 主启动类,使用@SpringBootApplication 注解标识:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringMvcDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringMvcDemoApplication.class, args);
    }
}

@SpringBootApplication 注解包含了@ComponentScan(组件扫描)、@EnableAutoConfiguration(自动配置)、@Configuration(配置类)三个核心注解,能够自动扫描当前包及其子包下的组件,并完成 SpringMVC 的自动配置。

3.2 第一个 SpringMVC 程序:Hello World

编写一个简单的 Controller,实现'Hello World'功能,验证 SpringMVC 环境是否搭建成功。

3.2.1 创建 Controller 类

在 com.example.springmvcdemo.controller 包下创建 HelloController 类,使用@Controller 注解标识控制器,使用@RequestMapping 注解映射请求路径:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
    // 映射请求路径:/hello
    @RequestMapping("/hello")
    @ResponseBody
    // 直接返回字符串,不进行视图渲染
    public String hello() {
        return "Hello SpringMVC!";
    }
}

说明:

  • @Controller:标识该类为 SpringMVC 的控制器组件,Spring 会自动扫描并将其纳入 IOC 容器管理;
  • @RequestMapping("/hello"):映射 HTTP 请求路径'/hello'到该方法;
  • @ResponseBody:表示该方法的返回值直接作为 HTTP 响应体返回,不经过视图解析器解析视图。如果不使用该注解,SpringMVC 会将返回值作为逻辑视图名进行解析。
3.2.2 启动项目并测试

运行主启动类 SpringMvcDemoApplication,启动成功后,打开浏览器访问'http://localhost:8080/hello',浏览器会显示'Hello SpringMVC!',说明 SpringMVC 环境搭建成功,请求处理正常。

3.3 请求参数绑定

SpringMVC 提供了强大的请求参数绑定功能,能够自动将 HTTP 请求参数绑定到 Controller 方法的参数上。常见的参数绑定场景包括基本类型参数、引用类型参数、集合类型参数等。

3.3.1 基本类型参数绑定

请求参数名与 Controller 方法参数名一致时,SpringMVC 会自动完成参数绑定。例如:

@RequestMapping("/user/find")
@ResponseBody
public String findUserById(Integer id, String name) {
    return "id: " + id + ", name: " + name;
}

访问 URL:'http://localhost:8080/user/find?id=1&name=zhangsan',响应结果:'id: 1, name: zhangsan'。

如果请求参数名与方法参数名不一致,可以使用@RequestParam 注解指定请求参数名:

@RequestMapping("/user/findByParam")
@ResponseBody
public String findByParam(@RequestParam("user_id") Integer id, @RequestParam("user_name") String name) {
    return "id: " + id + ", name: " + name;
}

访问 URL:'http://localhost:8080/user/findByParam?user_id=2&user_name=lisi',响应结果:'id: 2, name: lisi'。

3.3.2 引用类型参数绑定

当请求参数较多时,可以将参数封装为引用类型(如实体类),SpringMVC 会自动将请求参数绑定到实体类的属性上(要求请求参数名与实体类属性名一致)。

第一步:创建 User 实体类:

public class User {
    private Integer id;
    private String name;
    private Integer age;

    // 无参构造器、有参构造器、getter、setter 方法
    public User() {}

    public User(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // getter 和 setter 方法省略

    @Override
    public String toString() {
        return "User{id=" + id + ", name='" + name + "', age=" + age + "}";
    }
}

第二步:编写 Controller 方法:

@RequestMapping("/user/add")
@ResponseBody
public String addUser(User user) {
    return "添加用户:" + user.toString();
}

访问 URL:'http://localhost:8080/user/add?id=3&name=wangwu&age=25',响应结果:'添加用户:User{id=3, name='wangwu', age=25}'。

3.3.3 集合类型参数绑定

当需要传递多个同类型参数时(如批量删除用户的 ID 列表),可以使用集合类型(List、Map)接收参数。此时需要将集合参数封装到一个 VO(Value Object)类中,或者使用@RequestParam 注解指定参数名。

示例 1:使用 List 接收批量删除的 ID:

@RequestMapping("/user/deleteBatch")
@ResponseBody
public String deleteBatch(@RequestParam("ids") List<Integer> ids) {
    return "批量删除的 ID:" + ids.toString();
}

访问 URL:'http://localhost:8080/user/deleteBatch?ids=1&ids=2&ids=3',响应结果:'批量删除的 ID:[1, 2, 3]'。

示例 2:使用 VO 类封装集合参数(适用于复杂场景):

// 创建 UserVO 类
public class UserVO {
    private List<User> userList;

    // getter 和 setter 方法
    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }
}

// Controller 方法
@RequestMapping("/user/addBatch")
@ResponseBody
public String addBatch(UserVO userVO) {
    return "批量添加用户:" + userVO.getUserList().toString();
}

前端传递参数时,需要按照'userList[0].id=1&userList[0].name=zhangsan&userList[1].id=2&userList[1].name=lisi'的格式传递。

3.4 视图解析与页面跳转

在实际开发中,除了返回 JSON 数据(使用@ResponseBody),还经常需要返回页面视图。SpringMVC 通过视图解析器(ViewResolver)完成逻辑视图名到物理视图路径的解析。以下是基于 Thymeleaf 视图技术的页面跳转示例(Thymeleaf 是 Spring Boot 推荐的视图技术,比 JSP 更灵活、更强大)。

3.4.1 引入 Thymeleaf 依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3.4.2 配置视图解析器

Spring Boot 对 Thymeleaf 提供了自动配置,默认的视图解析规则如下:

  • 模板文件路径:classpath:/templates/
  • 模板文件后缀:.html
  • 逻辑视图名'index'会被解析为:classpath:/templates/index.html

如果需要自定义配置,可以在 application.properties 文件中添加以下配置:

# thymeleaf 模板前缀(默认 classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/pages/
# thymeleaf 模板后缀(默认.html)
spring.thymeleaf.suffix=.html
# 编码格式
spring.thymeleaf.encoding=UTF-8
# 模板模式
spring.thymeleaf.mode=HTML5
3.4.3 编写视图页面

在 classpath:/templates/目录下创建 index.html 文件:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <h1 th:text="${message}">欢迎访问首页</h1>
    <a href="@{/user/list}">查看用户列表</a>
</body>
</html>

在 classpath:/templates/目录下创建 user/list.html 文件:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户列表</title>
</head>
<body>
    <h1>用户列表</h1>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <tr th:each="user : ${userList}">
            <td th:text="${user.id}"></td>
            <td th:text="${user.name}"></td>
            <td th:text="${user.age}"></td>
        </tr>
    </table>
</body>
</html>
3.4.4 编写 Controller 方法实现页面跳转
@RequestMapping("/index")
public String toIndex(Model model) {
    // 向 Model 中存入数据,供视图页面使用
    model.addAttribute("message", "Hello SpringMVC + Thymeleaf!");
    // 返回逻辑视图名'index',视图解析器会解析为 classpath:/templates/index.html
    return "index";
}

@RequestMapping("/user/list")
public String userList(Model model) {
    // 模拟从数据库查询用户列表
    List<User> userList = new ArrayList<>();
    userList.add(new User(1, "zhangsan", 22));
    userList.add(new User(2, "lisi", 23));
    userList.add(new User(3, "wangwu", 24));
    // 向 Model 中存入用户列表
    model.addAttribute("userList", userList);
    // 返回逻辑视图名'user/list',解析为 classpath:/templates/user/list.html
    return "user/list";
}

测试:访问'http://localhost:8080/index',会跳转到 index.html 页面,显示'Hello SpringMVC + Thymeleaf!';点击'查看用户列表'链接,会跳转到 user/list.html 页面,显示用户列表数据。

四、SpringMVC 高级特性

4.1 拦截器(Interceptor)

SpringMVC 的拦截器类似于 Servlet 的过滤器(Filter),用于在请求处理的不同阶段对请求进行拦截和处理。拦截器可以实现权限控制、日志记录、参数校验、性能监控等功能。与 Filter 不同的是,拦截器是 SpringMVC 框架内部的组件,能够访问 Spring 的 IOC 容器,而 Filter 是 Servlet 规范的组件,作用范围更广。

4.1.1 拦截器的工作原理

拦截器通过实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类(已过时,推荐实现接口)来定义。HandlerInterceptor 接口提供了三个方法,对应拦截器的三个执行时机:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):在处理器(Handler)执行前执行。返回 true 表示放行,继续执行后续的拦截器和处理器;返回 false 表示拦截,不再执行后续操作。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):在处理器执行后、视图渲染前执行。可以通过 ModelAndView 对象对视图和数据进行修改。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):在视图渲染后、请求完成后执行。通常用于资源清理、日志记录等操作。
4.1.2 自定义拦截器实现

第一步:创建自定义拦截器类,实现 HandlerInterceptor 接口:

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 {
    // 处理器执行前拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 模拟登录验证:从 Session 中获取用户信息
        Object user = request.getSession().getAttribute("user");
        if (user == null) {
            // 未登录,重定向到登录页面
            response.sendRedirect(request.getContextPath() + "/login.html");
            return false;
        }
        // 已登录,放行
        return true;
    }

    // 处理器执行后、视图渲染前拦截
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可以修改 ModelAndView 中的数据或视图
        if (modelAndView != null) {
            modelAndView.addObject("interceptorMsg", "来自 LoginInterceptor 的消息");
        }
    }

    // 视图渲染后、请求完成后拦截
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 资源清理、日志记录等操作
        System.out.println("请求处理完成,执行资源清理...");
    }
}
4.1.3 配置拦截器

在 SpringMVC 中,需要通过配置类(实现 WebMvcConfigurer 接口)来注册拦截器,并指定拦截的请求路径和排除的请求路径。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 LoginInterceptor 拦截器
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/login.html", "/user/login"); // 排除登录页面和登录接口的请求
    }
}

说明:

  • addPathPatterns("/**"):表示拦截所有请求路径;
  • excludePathPatterns("/login.html", "/user/login"):表示排除对'/login.html'页面和'/user/login'接口的拦截,允许未登录用户访问这些资源。

4.2 异常处理

在 Web 应用开发中,异常处理是不可或缺的一部分。SpringMVC 提供了多种异常处理方式,能够统一捕获和处理 Controller 层的异常,避免异常直接暴露给用户,提升用户体验。常用的异常处理方式包括:@ExceptionHandler 注解、@ControllerAdvice 注解、实现 HandlerExceptionResolver 接口等。

4.2.1 @ExceptionHandler 注解(局部异常处理)

@ExceptionHandler 注解用于在 Controller 内部定义异常处理方法,只能处理当前 Controller 中的异常,属于局部异常处理。

@Controller
public class UserController {
    // 业务方法,可能抛出异常
    @RequestMapping("/user/get")
    @ResponseBody
    public String getUserById(Integer id) {
        if (id == null) {
            throw new NullPointerException("用户 ID 不能为空");
        }
        if (id <= 0) {
            throw new IllegalArgumentException("用户 ID 必须为正数");
        }
        return "用户 ID:" + id;
    }

    // 处理当前 Controller 中的 NullPointerException
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public String handleNullPointerException(NullPointerException e) {
        return "错误:" + e.getMessage();
    }

    // 处理当前 Controller 中的 IllegalArgumentException
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public String handleIllegalArgumentException(IllegalArgumentException e) {
        return "错误:" + e.getMessage();
    }
}
4.2.2 @ControllerAdvice + @ExceptionHandler(全局异常处理)

@ControllerAdvice 注解用于定义全局异常处理类,结合@ExceptionHandler 注解可以捕获所有 Controller 中的异常,实现全局异常统一处理。

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

// 全局异常处理类,捕获所有 Controller 的异常
@ControllerAdvice
public class GlobalExceptionHandler {
    // 处理 NullPointerException
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public String handleNullPointerException(NullPointerException e) {
        return "全局错误:" + e.getMessage();
    }

    // 处理 IllegalArgumentException
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public String handleIllegalArgumentException(IllegalArgumentException e) {
        return "全局错误:" + e.getMessage();
    }

    // 处理所有未捕获的异常(兜底处理)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public String handleException(Exception e) {
        return "系统异常:" + e.getMessage();
    }
}

使用全局异常处理后,所有 Controller 中抛出的异常都会被 GlobalExceptionHandler 中的对应方法捕获并处理,无需在每个 Controller 中单独定义异常处理方法。

4.3 文件上传

SpringMVC 提供了便捷的文件上传功能,基于 Apache Commons FileUpload 组件实现(Spring Boot 已自动整合相关依赖)。以下是文件上传的实现步骤:

4.3.1 引入文件上传依赖

Spring Boot 的 spring-boot-starter-web 依赖已包含文件上传所需的依赖,无需额外引入。如果是传统 SpringMVC 项目,需要手动引入以下依赖:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
4.3.2 配置文件上传解析器

Spring Boot 会自动配置 MultipartResolver(文件上传解析器),默认的最大上传文件大小为 1MB。如果需要自定义配置,可以在 application.properties 文件中添加以下配置:

# 单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
# 单次请求最大上传大小(多文件上传时)
spring.servlet.multipart.max-request-size=50MB
# 文件上传临时目录(默认在系统临时目录)
spring.servlet.multipart.location=${java.io.tmpdir}
4.3.3 实现文件上传功能

第一步:编写文件上传页面(upload.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="file"><br>
        <input type="submit" value="上传">
    </form>
</body>
</html>

注意:form 表单的 enctype 属性必须设置为'multipart/form-data',否则无法正确上传文件。

4.3.4 编写文件上传 Controller 方法
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@RestController
public class FileUploadController {
    // 文件上传路径(实际开发中建议配置在配置文件中)
    private static final String UPLOAD_PATH = "D:/upload/";

    @PostMapping("/file/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        // 检查文件是否为空
        if (file.isEmpty()) {
            return "文件不能为空";
        }
        // 获取文件名
        String originalFilename = file.getOriginalFilename();
        // 生成唯一文件名(避免文件名重复覆盖)
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
        // 创建上传目录(如果不存在)
        File uploadDir = new File(UPLOAD_PATH);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }
        try {
            // 保存文件到指定路径
            file.transferTo(new File(UPLOAD_PATH + fileName));
            return "文件上传成功!文件名:" + fileName;
        } catch (IOException e) {
            e.printStackTrace();
            return "文件上传失败:" + e.getMessage();
        }
    }
}

测试:访问'http://localhost:8080/upload.html',选择文件并点击'上传'按钮,文件会被保存到'D:/upload/'目录下,并返回上传结果。

五、SpringMVC 与其他技术的集成

5.1 SpringMVC 与 Spring 的集成

SpringMVC 本身就是 Spring 框架的一部分,因此与 Spring 的集成非常简单。在 Spring Boot 项目中,通过@SpringBootApplication 注解的@ComponentScan 功能,会自动扫描 Controller、Service、Repository 等组件,实现 Spring IOC 容器与 SpringMVC 的无缝集成。

在传统 SpringMVC 项目中,需要在 Web.xml 中配置 Spring 的 ContextLoaderListener,加载 Spring 的配置文件,实现 Spring IOC 容器的初始化。配置示例如下:

<!-- 配置 Spring 的 ContextLoaderListener,加载 Spring 配置文件 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
</context-param>

集成后,SpringMVC 的 Controller 可以直接通过@Autowired 注解注入 Spring IOC 容器中的 Service、DAO 等组件,实现业务逻辑的调用。

5.2 SpringMVC 与 MyBatis 的集成

MyBatis 是一款优秀的持久层框架,SpringMVC 与 MyBatis 的集成是企业级开发的常见组合。集成步骤如下:

5.2.1 引入依赖
<!-- MyBatis 核心依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>
<!-- MyBatis 与 Spring 集成依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.7</version>
</dependency>
<!-- 数据库驱动依赖(MySQL) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>
<!-- 数据源依赖(Druid) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.11</version>
</dependency>
5.2.2 配置数据源和 SqlSessionFactory

在 Spring 配置文件中配置数据源(Druid)、SqlSessionFactoryBean、MapperScannerConfigurer 等组件:

<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>
<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!-- 配置 MyBatis 映射文件路径 -->
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    <!-- 配置 MyBatis 全局配置文件 -->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 配置 Mapper 扫描器,自动扫描 Mapper 接口并创建代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.example.dao"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
5.2.3 编写 Mapper 接口和映射文件

创建 UserMapper 接口:

public interface UserMapper {
    User selectUserById(Integer id);
}

创建 UserMapper.xml 映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.UserMapper">
    <select id="selectUserById" parameterType="java.lang.Integer" resultType="com.example.entity.User">
        select id, name, age from user where id = #{id}
    </select>
</mapper>
5.2.4 在 Service 中注入 Mapper 接口
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User getUserById(Integer id) {
        return userMapper.selectUserById(id);
    }
}
5.2.5 在 Controller 中调用 Service
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/user/get/{id}")
    @ResponseBody
    public User getUserById(@PathVariable("id") Integer id) {
        return userService.getUserById(id);
    }
}

集成完成后,通过访问'http://localhost:8080/user/get/1',即可调用 MyBatis 查询数据库中的用户数据并返回。

六、总结与扩展

6.1 本文知识点总结

本文围绕 SpringMVC 知识点展开,采用总分总的编写模式,从基础到进阶,系统讲解了 SpringMVC 的核心内容。首先介绍了 MVC 设计模式和 SpringMVC 的基本概念、核心优势及应用场景,帮助读者建立对 SpringMVC 的整体认知;其次深入剖析了 SpringMVC 的核心组件(DispatcherServlet、HandlerMapping、HandlerAdapter 等)和执行流程,让读者理解 SpringMVC 的工作原理;然后通过基于 Spring Boot 的实战案例,讲解了 SpringMVC 的环境搭建、请求参数绑定、视图解析与页面跳转等基础应用;接着介绍了 SpringMVC 的高级特性,包括拦截器、异常处理、文件上传等,提升读者的实战能力;随后讲解了 SpringMVC 与 Spring、MyBatis 等技术的集成,满足企业级开发的需求;最后通过总结与扩展,梳理全文知识点,并提供进一步学习的阅读资料。

核心知识点梳理:

  • MVC 设计模式:模型(Model)、视图(View)、控制器(Controller)的职责划分;
  • SpringMVC 核心组件:DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)等的作用;
  • SpringMVC 执行流程:从接收请求到返回响应的完整步骤,各组件的协同工作机制;
  • 基础实战:环境搭建、请求参数绑定(基本类型、引用类型、集合类型)、视图解析与页面跳转;
  • 高级特性:拦截器(权限控制、日志记录)、异常处理(局部异常、全局异常)、文件上传;
  • 技术集成:与 Spring 的无缝集成、与 MyBatis 的持久层集成。

6.2 知识点扩展

除了本文讲解的核心知识点,SpringMVC 还有一些进阶内容值得深入学习,以应对更复杂的开发场景:

  • RESTful 风格 API 开发:RESTful 是一种软件架构风格,通过 HTTP 方法(GET、POST、PUT、DELETE)对应 CRUD 操作,实现资源的统一管理。SpringMVC 通过@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping 等注解实现 RESTful 风格 API 开发。

目录

  1. 前言
  2. 一、SpringMVC 概述
  3. 1.1 MVC 设计模式简介
  4. 1.2 SpringMVC 的定义与核心优势
  5. 1.3 SpringMVC 的应用场景
  6. 二、SpringMVC 核心原理与执行流程
  7. 2.1 SpringMVC 核心组件
  8. 2.1.1 前端控制器(DispatcherServlet)
  9. 2.1.2 处理器映射器(HandlerMapping)
  10. 2.1.3 处理器适配器(HandlerAdapter)
  11. 2.1.4 处理器(Handler)
  12. 2.1.5 视图解析器(ViewResolver)
  13. 2.1.6 视图(View)
  14. 2.1.7 模型和视图(ModelAndView)
  15. 2.2 SpringMVC 执行流程详解
  16. 三、SpringMVC 入门实战
  17. 3.1 环境搭建(基于 Spring Boot)
  18. 3.1.1 创建 Maven 项目
  19. 3.1.2 引入依赖
  20. 3.1.3 编写主启动类
  21. 3.2 第一个 SpringMVC 程序:Hello World
  22. 3.2.1 创建 Controller 类
  23. 3.2.2 启动项目并测试
  24. 3.3 请求参数绑定
  25. 3.3.1 基本类型参数绑定
  26. 3.3.2 引用类型参数绑定
  27. 3.3.3 集合类型参数绑定
  28. 3.4 视图解析与页面跳转
  29. 3.4.1 引入 Thymeleaf 依赖
  30. 3.4.2 配置视图解析器
  31. thymeleaf 模板前缀(默认 classpath:/templates/)
  32. thymeleaf 模板后缀(默认.html)
  33. 编码格式
  34. 模板模式
  35. 3.4.3 编写视图页面
  36. 3.4.4 编写 Controller 方法实现页面跳转
  37. 四、SpringMVC 高级特性
  38. 4.1 拦截器(Interceptor)
  39. 4.1.1 拦截器的工作原理
  40. 4.1.2 自定义拦截器实现
  41. 4.1.3 配置拦截器
  42. 4.2 异常处理
  43. 4.2.1 @ExceptionHandler 注解(局部异常处理)
  44. 4.2.2 @ControllerAdvice + @ExceptionHandler(全局异常处理)
  45. 4.3 文件上传
  46. 4.3.1 引入文件上传依赖
  47. 4.3.2 配置文件上传解析器
  48. 单个文件最大上传大小
  49. 单次请求最大上传大小(多文件上传时)
  50. 文件上传临时目录(默认在系统临时目录)
  51. 4.3.3 实现文件上传功能
  52. 4.3.4 编写文件上传 Controller 方法
  53. 五、SpringMVC 与其他技术的集成
  54. 5.1 SpringMVC 与 Spring 的集成
  55. 5.2 SpringMVC 与 MyBatis 的集成
  56. 5.2.1 引入依赖
  57. 5.2.2 配置数据源和 SqlSessionFactory
  58. 5.2.3 编写 Mapper 接口和映射文件
  59. 5.2.4 在 Service 中注入 Mapper 接口
  60. 5.2.5 在 Controller 中调用 Service
  61. 六、总结与扩展
  62. 6.1 本文知识点总结
  63. 6.2 知识点扩展
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 企业级 AI 编程挑战:百万行 Java 代码的长周期维护与高可靠实践
  • 2026 年 3 月 16 日 AI 深度早报:GTC 发布 Feynman 芯片与具身智能
  • 用两个栈模拟队列的算法实现与原理分析
  • C++ 类与对象:封装特性实现与实战详解
  • 基于 Python 和 Pygame 的彩球碰撞动画实现
  • 基于 Stable Diffusion 的多模态图像生成与识别系统
  • Python 标准 GUI 库 Tkinter 从入门到精通
  • 如何提升 Web 渗透测试能力与实战技巧
  • Linux 系统编程:Ext2 文件系统核心架构解析
  • Java 语言入门:设计哲学与 JVM 基础
  • MySQL 基础入门实战指南
  • Flutter 三方库 shelf_modular 的鸿蒙化适配指南
  • GitHub Copilot Pro 学生认证全流程指南
  • 向量数据库选型指南:主流方案对比与 Qdrant 推荐
  • 高并发秒杀系统设计:应对万人抢购的架构方案
  • llama.cpp 核心特性、技术原理及部署实践
  • 基于 Langchain-Chatchat 快速搭建本地 LLM 智能知识库
  • 基于 Java + SpringBoot + UniApp 的待办事项提醒小程序设计与实现
  • Python 爬虫基础入门与实战详解
  • GPU 云平台的 AI 创新实践与架构解析

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online