文章目录
1. 请求入口:用户请求到达 DispatcherServlet
3. 适配处理器:HandlerAdapter 统一调用接口
前言
首先,MVC模式 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将请求处理控制、业务逻辑、数据封装、数据显示等流程节点分离的思想来组织代码。如图所示:
所以,MVC 是一种设计模式,而Spring MVC 是一款基于MVC设计模式思想实现的的 MVC 框架,属于Spring技术栈的一部分。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring框架集成,更利于架构的设计与搭建。
一、Spring Mvc的核心组件
1:DispatcherServlet :核心处理器,负责统一接收请求、将请求分发至不同的控制器,并负责客户端响应。它的地位相当于 “中央调度器”,简化了组件间的耦合,是 Spring MVC 流程的核心驱动者。
2:HandlerMapping :处理器映射器,根据 uri去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。
- 常见实现:
RequestMappingHandlerMapping
:处理@RequestMapping
注解的 Controller 方法(最常用);BeanNameUrlHandlerMapping
:根据 Bean 的名称(需以/
开头)映射请求 URL。
3:HandlerAdapter:处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;
- 常见实现:
RequestMappingHandlerAdapter
:适配@Controller
+@RequestMapping
注解的处理器(最常用);SimpleControllerHandlerAdapter
:适配实现Controller
接口的处理器。
4:Handler :请求处理器,处理实际请求的处理器。
5:ViewResolver :视图解析器,根据 Handler返回的逻辑视图名称,解析并渲染真正的视图文件,并传递给 DispatcherServlet响应至客户端
这些组件通过 DispatcherServlet 串联,形成完整流程。这种设计通过接口解耦,使各组件可灵活替换(如替换视图解析器支持不同模板引擎),体现了 Spring 的 “开闭原则”。
二、Spring Mvc 的执行流程。
如图所示:
SpringMVC 是基于 MVC 设计模式的 Web 框架,其核心是通过 DispatcherServlet(前端控制器)协调多个组件完成请求处理。以下从执行流程的 11 个核心步骤展开,下面我们详细解析各环节的实现逻辑。
1. 请求入口:用户请求到达 DispatcherServlet
用户发送的 HTTP 请求(GET/POST 等)首先被 DispatcherServlet
接收。DispatcherServlet
继承自 HttpServlet
,其核心处理逻辑在 doDispatch()
方法中,所有请求最终都会进入该方法:
// DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 找到当前请求对应的处理器执行链(核心步骤)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 没有找到处理器,返回 404
noHandlerFound(processedRequest, response);
return;
}
// 找到支持当前处理器的适配器(核心步骤)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 执行拦截器的 preHandle 方法(前置处理)
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return; // 若有拦截器返回 false,终止流程
}
// 调用处理器(Controller)并返回 ModelAndView(核心步骤)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 处理默认视图名(若 Controller 未指定视图名)
applyDefaultViewName(processedRequest, mv);
// 执行拦截器的 postHandle 方法(后置处理)
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
}
// 处理结果:渲染视图 + 执行拦截器 afterCompletion(核心步骤)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
// 异常时执行拦截器的 afterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} finally {
// 1清理文件上传请求资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
2. 查找处理器:HandlerMapping 定位处理器
DispatcherServlet
通过 HandlerMapping
接口的实现类(如 RequestMappingHandlerMapping
)根据请求 URL 查找对应的处理器(Controller
方法),并封装为 HandlerExecutionChain
(包含处理器和拦截器)。
核心源码(getHandler()
方法):
// DispatcherServlet
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
// 遍历所有 HandlerMapping,找到第一个匹配的处理器
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
- 关键实现:
RequestMappingHandlerMapping
会在启动时扫描所有@Controller
类中的@RequestMapping
注解,建立 URL 与 Controller 方法的映射关系,请求时直接根据 URL 匹配。3. 适配处理器:HandlerAdapter 统一调用接口
由于处理器(Controller 方法)的类型可能不同(如注解式、接口式),
DispatcherServlet
通过HandlerAdapter
接口适配不同类型的处理器,统一调用方式。核心源码(
getHandlerAdapter()
方法):protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { // 判断适配器是否支持当前处理器 if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]"); }
- 常用适配器:
RequestMappingHandlerAdapter
用于处理注解式 Controller(@Controller
+@RequestMapping
),是最常用的实现。 -
4. 拦截器前置处理:preHandle ()
HandlerExecutionChain
中的拦截器(HandlerInterceptor
)会在处理器执行前调用preHandle()
方法,可用于权限校验、日志记录等。核心源码(
applyPreHandle()
方法): -
// HandlerExecutionChain boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { // 正序执行拦截器的 preHandle for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { // 若当前拦截器返回 false,触发后续拦截器的 afterCompletion 并终止 triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true; }
5. 执行处理器:调用 Controller 方法
HandlerAdapter
调用处理器(Controller 方法),执行业务逻辑并返回ModelAndView
(包含视图名和模型数据)。以
RequestMappingHandlerAdapter
为例,核心调用逻辑在invokeHandlerMethod()
方法: -
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // 解析请求参数 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // 创建 ServletInvocableHandlerMethod 用于执行 Controller 方法 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); invocableMethod.setMessageConverters(this.messageConverters); // ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); // 执行 Controller 方法(核心) invocableMethod.invokeAndHandle(webRequest, mavContainer); // 返回 ModelAndView return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
- 结果:Controller 方法执行后,返回
ModelAndView
(例如new ModelAndView("index", "msg", "Hello")
表示视图名为index
,模型数据为msg=Hello
)。 -
6. 拦截器后置处理:postHandle ()
处理器执行完成后,
HandlerExecutionChain
会调用拦截器的postHandle()
方法,可用于修改模型数据或视图(在视图渲染前执行)7. 解析视图:ViewResolver 解析视图名
DispatcherServlet
通过ViewResolver
将ModelAndView
中的逻辑视图名(如"index"
)解析为物理视图对象(如 JSP 路径/WEB-INF/views/index.jsp
)。8. 渲染视图:填充模型数据到视图
View
对象的render()
方法将模型数据(Model
)填充到视图中,生成最终的响应内容(如 HTML)。9. 拦截器完成处理:afterCompletion ()
视图渲染完成后(无论成功或失败),
HandlerExecutionChain
会调用拦截器的afterCompletion()
方法,用于资源清理(如关闭流、释放锁)。10. 响应客户端
最终,渲染后的视图内容通过
HttpServletResponse
返回给用户,完成整个请求流程。
---------------------------------------------------------------------------------------------------------------------------------
-
核心设计模式与总结
-
设计模式:
- 前端控制器模式(
DispatcherServlet
统一调度); - 适配器模式(
HandlerAdapter
适配不同处理器); - 责任链模式(拦截器链
HandlerExecutionChain
)。
- 前端控制器模式(
-
流程核心:
以DispatcherServlet
为中心,通过HandlerMapping
找处理器、HandlerAdapter
执行处理器、ViewResolver
解析视图,配合拦截器实现请求的完整生命周期管理,各组件通过接口解耦,体现了 Spring “高内聚、低耦合” 的设计思想。今天依旧是深蹲不写BUG,我们继续努力!!