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

目录

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

1. 什么是 MVC 设计模式?

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

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

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

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

1. 环境准备(Maven 依赖)

2. Java 核心配置类

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

(2)Spring MVC 配置类(WebConfig)

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

五、核心注解与请求处理

1. 控制器注解

2. 请求映射注解

示例:请求映射

3. 请求参数绑定注解

示例:参数绑定

六、数据模型与视图渲染

1. 向视图传递数据

示例:Model 传递数据

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

2. RESTful 接口返回 JSON

示例:返回 JSON

七、拦截器(HandlerInterceptor)

1. 自定义拦截器

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

八、异常处理

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

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

九、高级特性

1. 跨域请求处理(CORS)

2. 文件上传

3. 异步请求处理

十、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 依赖)



    org.springframework
    spring-webmvc
    5.3.20



    javax.servlet
    javax.servlet-api
    4.0.1
    provided



    org.thymeleaf
    thymeleaf-spring5
    3.0.12.RELEASE

2. Java 核心配置类

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

通过 AbstractAnnotationConfigDispatcherServletInitializer 配置 DispatcherServlet 和 Spring 容器:

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)
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 的 )
@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)
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 风格。
示例:请求映射
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:绑定请求参数到实体对象(表单提交常用)。
示例:参数绑定
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 传递数据
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 userList = Arrays.asList(
            new User("张三", 20),
            new User("李四", 25)
        );
        // 添加数据到模型,视图中可通过 "users" 访问
        model.addAttribute("users", userList);
        model.addAttribute("title", "用户列表");
        return "user/list"; // 返回视图名称
    }
}
Thymeleaf 视图渲染(user/list.html)



    
    用户列表


    

用户列表

姓名 年龄
张三 20

2. RESTful 接口返回 JSON

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



    com.fasterxml.jackson.core
    jackson-databind
    2.12.5
示例:返回 JSON
@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. 自定义拦截器

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 中配置)

@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 的异常:

@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 的异常:

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 或全局配置支持跨域:

// 局部跨域(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 请求:

// 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. 异步请求处理

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

@RestController
@RequestMapping("/async")
public class AsyncController {
    @GetMapping("/task")
    public Callable 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 网关或服务接口。

posted @ 2026-01-05 14:38  clnchanpin  阅读(278)  评论(0)    收藏  举报