前言
在 Java Web 开发的世界里,其底层处理 HTTP 请求的核心机制依然 Spring MVC。
很多初学者会觉得 Spring MVC 像一个黑盒:我们在浏览器输入 URL,敲下回车,屏幕上就出现了数据。这中间到底发生了什么?
今天,我们就拆开这个黑盒,用通俗易懂的方式,带你走完一次 HTTP 请求。
一、 核心架构:一种“分工明确”的设计
Spring MVC 的设计灵感来源于经典的 MVC (Model-View-Controller) 设计模式,但它通过引入一个“中央调度器”,将职责划分得更加极致。
我们可以将其想象成一家米其林餐厅的运作流程:
-
DispatcherServlet(前台经理/调度员):
-
核心角色。它是整个框架的“心脏”。所有请求必须先经过它,由它负责分发任务,它自己不干活,只负责指挥。
-
-
HandlerMapping(点餐员/菜单):
-
负责根据 URL 找到对应的处理器(Controller)。它知道“哪位厨师负责做这道菜”。
-
-
HandlerAdapter(厨房调度/适配器):
-
负责执行处理器(Controller)。因为 Controller 的写法千变万化,适配器负责屏蔽差异,统一调用。
-
-
Controller(大厨):
-
开发者最熟悉的组件。负责接收参数、调用业务逻辑(Service)、返回数据。
-
-
ViewResolver(摆盘师/视图解析器):
-
负责将数据(Model)和页面模板(View)结合,渲染出最终的 HTML。
-
二、 七步走:请求的生命周期
当一个 HTTP 请求到达服务器时,它会经历以下 7 个关键步骤:
1. 拦截请求 (The Interception)
用户在浏览器发起请求(如 GET /user/profile)。这个请求首先会被部署在 Tomcat 中的 DispatcherServlet 捕获。
注意:在 Spring Boot 中,DispatcherServlet 会自动配置并映射到
/,即拦截所有请求。
2. 查找处理器 (Lookup)
DispatcherServlet 此时并不知道这个 URL 该由谁处理。它会查询 HandlerMapping。
-
HandlerMapping 会扫描所有的
@RequestMapping注解,建立 URL 到 Controller 方法的映射关系。 -
结果:返回一个 执行链 (Execution Chain),其中包含具体的 Controller 对象和可能存在的拦截器 (Interceptors)。
3. 请求适配 (Adaptation)
拿到了 Controller,但 DispatcherServlet 不会直接调用它(因为 Controller 可能有多种实现方式)。它会把任务交给 HandlerAdapter。
-
HandlerAdapter 的作用就是“翻译”,通过反射机制调用具体的 Controller 方法。
4. 业务处理 (Execution) —— 核心步骤
此时,终于轮到我们写的代码登场了。Controller 开始工作:
-
接收参数(自动封装 Form 表单或 JSON)。
-
调用 Service 层进行业务逻辑处理(如查数据库)。
-
结果:Controller 执行完毕,通常会返回两个东西:
-
Model:处理后的数据。
-
View:数据的展示方式(逻辑视图名)。
-
(注:如果是前后端分离项目,这里会发生变化,详见下文)
-
5. 视图解析 (View Resolution)
DispatcherServlet 拿到了 ModelAndView,但它还是看不懂 "success" 或 "user_detail" 到底是什么。它会求助于 ViewResolver。
-
ViewResolver 会根据配置(如
prefix="/WEB-INF/",suffix=".jsp"),找到真正的物理视图文件。
6. 视图渲染 (Rendering)
通过视图解析器,Model 中的数据被填充到 View 模板中(JSP, Thymeleaf, Freemarker)。
-
这一步生成了最终用户能看到的 HTML 代码。
7. 响应用户 (Response)
最后,DispatcherServlet 将渲染好的 HTML(或数据)通过 HTTP 响应流返回给浏览器。用户看到了页面。
三、 现代化的变迁:前后端分离与 RESTful
在现代开发(尤其是 React/Vue + Spring Boot)中,上述流程的第 5、6 步通常会被省略。
为什么? 因为我们不再由后端生成 HTML,而是直接返回 JSON 数据。
关键差异点:
-
注解变化:我们使用
@RestController(等同于@Controller+@ResponseBody)。 -
组件介入:
HttpMessageConverter替代了ViewResolver。-
当 HandlerAdapter 检测到
@ResponseBody注解时,它不会去走视图解析的流程,而是直接利用消息转换器(如 Jackson),将 Java 对象序列化为 JSON 字符串。
-
-
流程简化:
Request -> DispatcherServlet -> HandlerMapping -> HandlerAdapter -> Controller -> JSON -> Response
四、 源码级的小细节(面试加分项)
-
单例问题: Spring 中的 Controller 默认是单例 (Singleton) 的。这意味着多个线程会同时访问同一个 Controller 实例。
-
警示:千万不要在 Controller 里定义成员变量(比如
private int count)来存储请求状态,否则会引发严重的线程安全问题!
-
-
拦截器 (Interceptor) vs 过滤器 (Filter):
-
Filter:属于 Servlet 规范,工作在 DispatcherServlet 之前。
-
Interceptor:属于 Spring 框架,工作在 DispatcherServlet 内部(第 2 步和第 3 步之间)。它可以精确地控制对某个具体的 Controller 方法进行拦截。
-
结语
Spring MVC 的强大之处在于其高度的解耦。通过将请求处理拆解为一个个独立的组件,开发者可以专注于业务逻辑(Controller),而无需操心 HTTP 协议的解析、视图的渲染等底层细节。


被折叠的 条评论
为什么被折叠?



