Spring MVC 深度解析:原理、源码剖析与实战

Spring MVC 深度解析:原理、源码剖析与实战

在 Spring 体系中,Spring MVC 作为 Web 层的核心框架,承担着请求处理、参数解析、视图渲染等关键任务。今天,我们将深入剖析 Spring MVC 的执行流程 ,结合 源码分析 ,并通过 代码实战 掌握其核心机制。


📌 1. 什么是 Spring MVC?

Spring MVC(Model-View-Controller)是一种基于 Servlet 的 Web 框架,遵循 MVC 设计模式,主要负责:

  • 请求分发(DispatcherServlet)
  • 控制器映射(HandlerMapping)
  • 参数解析(HandlerAdapter)
  • 视图渲染(ViewResolver)

📌 2. Spring MVC 执行流程解析

Spring MVC 处理请求的完整流程如下:

1️⃣ 客户端发送 HTTP 请求 (如 GET /user/list

2️⃣ DispatcherServlet 拦截请求 ,作为 MVC 的中央调度器

3️⃣ HandlerMapping 查找对应的 Controller (基于 URL 映射)

4️⃣ HandlerAdapter 适配执行 Controller 业务逻辑

5️⃣ Controller 处理请求并返回 ModelAndView

6️⃣ ViewResolver 解析视图并渲染数据

7️⃣ 返回 HTML 响应给客户端

📌 Spring MVC 内部架构图

复制代码
[Client] → [DispatcherServlet] → [HandlerMapping] → [Controller] → 
[ModelAndView] → [ViewResolver] → [Response]

📌 3. 源码解析:DispatcherServlet 如何工作?

🔥 DispatcherServlet 核心源码

Spring MVC 通过 DispatcherServlet 作为 前端控制器 ,其核心方法 doDispatch() 负责处理请求:

java 复制代码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1️⃣ 解析请求对应的 Handler(Controller)
    HandlerExecutionChain handler = getHandler(request);
    
    // 2️⃣ 选择合适的 HandlerAdapter 执行 Controller 方法
    HandlerAdapter ha = getHandlerAdapter(handler.getHandler());
    
    // 3️⃣ 调用 Controller 方法,获取 ModelAndView
    ModelAndView mv = ha.handle(request, response, handler.getHandler());

    // 4️⃣ 解析视图,并返回响应结果
    processDispatchResult(request, response, handler, mv);
}

核心流程

  • getHandler():查找 HandlerMapping 获取对应的 Controller
  • getHandlerAdapter():找到适配 Controller 方法的 HandlerAdapter
  • handle():执行 Controller 逻辑,返回 ModelAndView
  • processDispatchResult():调用 ViewResolver 解析视图,渲染响应

📌 4. 代码实战:手写 Spring MVC Controller

我们基于 Spring Boot 构建一个简单的 Spring MVC 应用,并实现 @RequestMapping 的 Controller。

📝 代码示例:Spring Boot MVC 控制器

java 复制代码
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("/user")
public class UserController {
    
    // 模拟数据库存储用户
    private static List<String> users = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie"));

    // 查询用户列表
    @GetMapping("/list")
    public List<String> listUsers() {
        return users;
    }

    // 添加用户
    @PostMapping("/add")
    public String addUser(@RequestParam String name) {
        users.add(name);
        return "用户 " + name + " 添加成功!";
    }
}

🛠 启动 Spring Boot

SpringBootApplication 类中运行:

java 复制代码
@SpringBootApplication
public class SpringMvcApp {
    public static void main(String[] args) {
        SpringApplication.run(SpringMvcApp.class, args);
    }
}

测试 API

shell 复制代码
# 查询用户列表
curl http://localhost:8080/user/list

# 添加新用户
curl -X POST "http://localhost:8080/user/add?name=David"

📌 5. 深入分析 @RequestMapping 的执行流程

@RequestMapping 是 Spring MVC 用于 URL 映射 的核心注解,它的执行流程如下:

1️⃣ Spring MVC 启动时,扫描 @RequestMapping 标注的方法

2️⃣ HandlerMapping 解析 URL,并映射到 Controller 方法

3️⃣ HandlerAdapter 调用 Controller 方法,解析 @RequestParam 参数

4️⃣ 返回结果封装为 ResponseBody,通过 HttpMessageConverter 处理

📌 源码解析:Spring MVC 如何解析 @RequestMapping?

java 复制代码
@RequestMapping("/user")
public class UserController {
    @GetMapping("/list")
    public List<String> listUsers() { return users; }
}

➡️ 核心逻辑

Spring MVC 在启动时,会通过 RequestMappingHandlerMapping 解析 @RequestMapping 并存入映射表:

java 复制代码
protected void detectHandlerMethods(Object handler) {
    for (Method method : handler.getClass().getDeclaredMethods()) {
        if (method.isAnnotationPresent(RequestMapping.class)) {
            registerHandlerMethod(handler, method);
        }
    }
}

📌 6. Spring MVC 过滤器与拦截器

Spring MVC 提供 FilterInterceptor 机制,可用于 用户认证、日志记录、跨域请求 等场景。

类型 作用 实现方式
Filter 过滤 HTTP 请求 javax.servlet.Filter
Interceptor 拦截 Controller HandlerInterceptor

📝 代码示例:拦截器实现日志记录

java 复制代码
@Component
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("请求路径:" + request.getRequestURI());
        return true;
    }
}

注册拦截器

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LogInterceptor());
    }
}

🔹 作用:每次请求前打印日志,方便调试。


📌 7. 总结

功能 Spring 机制 源码解析 代码实战
请求分发 DispatcherServlet doDispatch() 方法 @RequestMapping
Controller 处理 HandlerMapping getHandler() @RestController
参数解析 HandlerAdapter handle() 方法 @RequestParam
视图渲染 ViewResolver processDispatchResult() return ModelAndView

今日收获

  • 掌握 Spring MVC 执行流程
  • 深入理解 DispatcherServlet 处理逻辑
  • 解析 @RequestMapping 的工作机制
  • 实战 Spring Boot MVC 开发
  • 实现 日志拦截器

🚀 明日预告:Spring 事务管理(事务传播、@Transactional 源码分析)

🔗 学习资料

📖 Spring 官方文档 - MVC


💬 Spring MVC 你有什么疑问?欢迎留言交流! 🚀

相关推荐
Remember_Ray3 分钟前
重学Java基础篇—什么是快速失败(fail-fast)和安全失败(fail-safe)?
java
奋进的小暄3 分钟前
贪心算法(12))(java)坏了的计算器
java·算法·贪心算法
无奈何杨7 分钟前
Docker部署MySQL、Redis、Kafka、ES、Kibana
后端
Goboy9 分钟前
老婆问我:“什么是大模型的“幻觉”?”
后端·程序员·架构
RainbowSea10 分钟前
2. RabbitMQ 的详细安装步骤(两种方式,第一种:yum 安装;第二种:docker 容器安装)
java·消息队列·rabbitmq
小鱼人爱编程19 分钟前
Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式
java·前端·后端
Mr.wangh22 分钟前
SpringBoot 配置⽂件
java·spring boot·spring
RainbowSea22 分钟前
1. 初始 RabbitMQ 消息队列
java·消息队列·rabbitmq
小鱼人爱编程25 分钟前
当上小组长的第3天,我裁掉了2年老员工
前端·后端·面试
Edward-tan29 分钟前
Django接入 免费的 AI 大模型——讯飞星火(2025年4月最新!!!)
后端·python·django