💡 核心入口: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内部的核心步骤,我将配合每个步骤的源码进行深入解读。
checkMultipart:处理文件上传
流程开始,会检查当前请求是否是一个multipart/form-data类型的文件上传请求。如果是,则通过配置的MultipartResolver将HttpServletRequest对象包装为MultipartHttpServletRequest,以便后续方便地获取上传的文件。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;}最常用的
HandlerMapping是RequestMappingHandlerMapping,它在项目启动时,会扫描所有标注了@Controller和@RequestMapping的类和方法,将请求路径(和HTTP方法)与目标方法(封装为HandlerMethod对象)的映射关系保存起来。getHandler方法的核心逻辑就在AbstractHandlerMethodMapping.lookupHandlerMethod中,它会根据请求路径在内部的mappingRegistry中进行精准匹配。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为代表)的核心。拦截器「前置处理」:
applyPreHandle
在真正调用处理器方法之前,applyPreHandle方法会按照顺序执行处理器执行链中所有拦截器的preHandle方法。如果任何一个拦截器的
preHandle方法返回false,整个请求链路将在此被切断,后续的处理器方法和视图渲染都不会执行。ha.handle:执行处理器
这是核心的业务处理阶段。HandlerAdapter的handle方法会利用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(...);}拦截器「后置处理」:
applyPostHandle
在处理器方法执行完毕、但视图尚未渲染之前,applyPostHandle方法会按逆序执行所有拦截器的postHandle方法。如果处理器方法执行过程中抛出了异常,
postHandle方法将不会被执行。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);}// ... 清理和后续处理}- 异常处理:如果处理器执行过程中抛出了异常,它会调用配置的
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);}- 解析视图:遍历所有
拦截器「完成处理」:
triggerAfterCompletion
无论请求是正常处理完成,还是中途发生了异常,triggerAfterCompletion方法都会在最后被调用,按逆序执行所有拦截器的afterCompletion方法,用于执行清理资源等收尾工作。