news 2026/5/10 12:26:48

一个请求在spring MVC 中是怎么流转的

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一个请求在spring MVC 中是怎么流转的

💡 核心入口:DispatcherServlet

所有Spring MVC请求的入口都是DispatcherServlet。它本质上是一个Servlet,其service()方法(由父类FrameworkServlet实现)最终会导向其核心方法doDispatch()。这个方法就像一个指挥中心,调度其他组件来完成请求处理。

// FrameworkServlet.java@OverrideprotectedfinalvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{processRequest(request,response);}// ... doPost, doPut, doDelete等方法类似// processRequest方法最终会调用到DispatcherServlet的doService()方法
// DispatcherServlet.java@OverrideprotectedvoiddoService(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{// ... 做一些准备工作和属性设置 ...doDispatch(request,response);// 核心分发逻辑}

🚦 请求全链路剖析:doDispatch() 源码逐段解析

下面的流程图清晰地展示了doDispatch内部的核心步骤,我将配合每个步骤的源码进行深入解读。

“如果返回false则中断”

“如果返回true则继续”

客户端发起请求

DispatcherServlet接收请求

checkMultipart
检查是否为文件上传请求

getHandler
通过HandlerMapping获取处理器执行链

getHandlerAdapter
获取支持该处理器的适配器

applyPreHandle
执行拦截器的preHandle方法

响应返回

ha.handle
适配器执行处理器方法

applyPostHandle
执行拦截器的postHandle方法

processDispatchResult
处理结果及异常

render
视图渲染

triggerAfterCompletion
执行拦截器的afterCompletion方法

  1. checkMultipart:处理文件上传
    流程开始,会检查当前请求是否是一个multipart/form-data类型的文件上传请求。如果是,则通过配置的MultipartResolverHttpServletRequest对象包装为MultipartHttpServletRequest,以便后续方便地获取上传的文件。

  2. getHandler:定位处理器
    接下来,系统需要找到“谁来处理这个请求”。getHandler(request)方法会遍历注册的HandlerMapping组件,找到能处理当前请求的处理器(Handler),并返回一个包含该处理器和其关联的HandlerInterceptor(拦截器)的执行链。

    // DispatcherServlet.javaprotectedHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{if(this.handlerMappings!=null){// 遍历所有注册的处理器映射器for(HandlerMappingmapping:this.handlerMappings){HandlerExecutionChainhandler=mapping.getHandler(request);if(handler!=null){returnhandler;// 返回第一个找到的处理器执行链}}}returnnull;}

    最常用的HandlerMappingRequestMappingHandlerMapping,它在项目启动时,会扫描所有标注了@Controller@RequestMapping的类和方法,将请求路径(和HTTP方法)与目标方法(封装为HandlerMethod对象)的映射关系保存起来。getHandler方法的核心逻辑就在AbstractHandlerMethodMapping.lookupHandlerMethod中,它会根据请求路径在内部的mappingRegistry中进行精准匹配。

  3. getHandlerAdapter:查找适配器
    找到处理器后,DispatcherServlet需要一种统一的方式来调用它,因为处理器的形式可能是多样的(如实现Controller接口的类,或是标注了@RequestMapping的方法)。getHandlerAdapter方法的作用就是遍历所有注册的HandlerAdapter,找到能“支持”当前处理器的那个适配器,并在后续操作中使用它。

    // DispatcherServlet.javaprotectedHandlerAdaptergetHandlerAdapter(Objecthandler)throwsServletException{if(this.handlerAdapters!=null){// 遍历所有注册的处理器适配器for(HandlerAdapteradapter:this.handlerAdapters){if(adapter.supports(handler)){// 判断是否支持该处理器returnadapter;// 返回第一个找到的适配器}}}thrownewServletException("No adapter for handler...");}

    对于@RequestMapping注解的方法,Spring MVC会为其选择RequestMappingHandlerAdapter。这个适配器是处理现代Spring MVC控制器(以@Controller@RequestMapping为代表)的核心。

  4. 拦截器「前置处理」:applyPreHandle
    在真正调用处理器方法之前,applyPreHandle方法会按照顺序执行处理器执行链中所有拦截器的preHandle方法。

    如果任何一个拦截器的preHandle方法返回false,整个请求链路将在此被切断,后续的处理器方法和视图渲染都不会执行。

  5. ha.handle:执行处理器
    这是核心的业务处理阶段。HandlerAdapterhandle方法会利用Java的反射机制调用真正的Controller方法。在这个过程中,HandlerAdapter还会负责处理诸多繁重的工作,例如:

    • 参数解析:将请求参数(Query String、Form Data、JSON等)绑定到方法参数上。
    • 返回值处理:将方法返回的对象(如ModelAndView、POJO、ResponseEntity等)转换为统一的ModelAndView对象。
    // RequestMappingHandlerAdapter.java (精简逻辑)@OverrideprotectedModelAndViewhandleInternal(HttpServletRequestrequest,HttpServletResponseresponse,HandlerMethodhandlerMethod)throwsException{ModelAndViewmav=null;// ...// 最终会委托给 ServletInvocableHandlerMethod 来调用 Controller 方法ServletInvocableHandlerMethodinvocableMethod=...;invocableMethod.invokeAndHandle(request,response,mavContainer);// ...returngetModelAndView(...);}
  6. 拦截器「后置处理」:applyPostHandle
    在处理器方法执行完毕、但视图尚未渲染之前,applyPostHandle方法会按逆序执行所有拦截器的postHandle方法。

    如果处理器方法执行过程中抛出了异常,postHandle方法将不会被执行。

  7. processDispatchResult:处理结果
    这个方法负责处理执行结果,主要包含两个子任务:

    • 异常处理:如果处理器执行过程中抛出了异常,它会调用配置的HandlerExceptionResolver组件来解析异常,生成一个包含错误视图的ModelAndView
    • 视图渲染:调用render方法,渲染最终的响应结果。
    // DispatcherServlet.javaprivatevoidprocessDispatchResult(HttpServletRequestrequest,HttpServletResponseresponse,@NullableHandlerExecutionChainmappedHandler,@NullableModelAndViewmv,@NullableExceptionexception)throwsException{// 1. 处理异常if(exception!=null){// 调用 HandlerExceptionResolver 来解析异常,生成对应的 ModelAndViewmv=processHandlerException(request,response,mappedHandler,exception);}// 2. 视图渲染if(mv!=null&&!mv.wasCleared()){render(mv,request,response);}// ... 清理和后续处理}
  8. render:视图渲染
    如果ModelAndView包含视图信息(非@ResponseBody),该方法会执行:

    • 解析视图:遍历所有ViewResolver,调用其resolveViewName方法,将逻辑视图名(如"user/list")解析为一个具体的View对象(如InternalResourceView,对应/WEB-INF/jsp/userList.jsp)。
    • 渲染输出:调用View对象的render方法,将模型数据(Model)填充到视图中,生成最终的HTML(或其他格式)内容,并写入HttpServletResponse
    // DispatcherServlet.javaprotectedvoidrender(ModelAndViewmv,HttpServletRequestrequest,HttpServletResponseresponse)throwsException{// 解析视图名称Viewview=null;if(mv.isReference()){// 遍历 ViewResolver 来解析视图名称view=resolveViewName(mv.getViewName(),mv.getModelInternal(),locale,request);}// 渲染视图view.render(mv.getModelInternal(),request,response);}
  9. 拦截器「完成处理」:triggerAfterCompletion
    无论请求是正常处理完成,还是中途发生了异常,triggerAfterCompletion方法都会在最后被调用,按逆序执行所有拦截器的afterCompletion方法,用于执行清理资源等收尾工作。


🔗 总览:请求流转全路径总结图

ViewViewResolverHandlerExceptionResolverControllerHandlerAdapterHandlerInterceptorHandlerMappingDispatcherServlet客户端ViewViewResolverHandlerExceptionResolverControllerHandlerAdapterHandlerInterceptorHandlerMappingDispatcherServlet客户端alt[存在异常]alt[preHandle返回true][preHandle返回false]发送请求checkMultipart (文件上传检查)getHandler (定位处理器)返回 HandlerExecutionChaingetHandlerAdapter (获取适配器)applyPreHandle (前置拦截)handle (执行处理器)返回ModelAndViewapplyPostHandle (后置拦截)processDispatchResult (处理结果)processHandlerException (解析异常)返回错误 ModelAndViewresolveViewName (解析视图)返回View对象render (视图渲染)返回响应直接返回 (请求中断)triggerAfterCompletion (完成清理)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 12:26:48

从‘Hello World’到第一个爬虫:Python新手避坑指南与实战路线图

从零到爬虫:Python新手避坑实战手册 1. 环境配置:避开第一个深坑 Python爬虫之旅的第一步往往就卡在了环境配置上。很多新手在安装Python和PyCharm时会遇到各种奇怪的问题,比如环境变量配置错误、版本不兼容等。以下是经过实战验证的配置方案…

作者头像 李华
网站建设 2026/5/10 12:26:39

如何彻底移除Windows Defender:3种模式终极优化指南

如何彻底移除Windows Defender:3种模式终极优化指南 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_mirrors/wi/wi…

作者头像 李华
网站建设 2026/5/10 12:25:39

八大网盘直链解析神器:LinkSwift让你的下载速度飙升10倍!

八大网盘直链解析神器:LinkSwift让你的下载速度飙升10倍! 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移…

作者头像 李华
网站建设 2026/5/10 12:25:39

使用Nodejs和Taotoken快速搭建一个简易的AI对话服务后端

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用Nodejs和Taotoken快速搭建一个简易的AI对话服务后端 对于前端或Node.js开发者而言,快速构建一个具备AI对话能力的后…

作者头像 李华
网站建设 2026/5/10 12:24:44

思源宋体:让设计摆脱字体版权困扰的优雅解决方案

思源宋体:让设计摆脱字体版权困扰的优雅解决方案 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 还在为商业项目中的字体选择而头疼吗?面对高昂的字体授权费用和…

作者头像 李华
网站建设 2026/5/10 12:21:30

TikTok评论采集终极指南:免费开源工具快速提取用户反馈数据

TikTok评论采集终极指南:免费开源工具快速提取用户反馈数据 【免费下载链接】TikTokCommentScraper 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokCommentScraper 想要深入了解TikTok用户的真实想法吗?TikTokCommentScraper是一款强大而简…

作者头像 李华