摘要:本文分析了SpringMVC的工作流程,包括请求处理的各个阶段和核心对象的协作机制。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
Tomcat 8.5.50
Maven 3.6.3
Spring 5.2.25.RELEASE
1 基本流程
SpringMVC的工作流程是围绕DispatcherServlet前端控制器展开的,由它统一处理所有请求。
核心流程:

说明:
- 发送请求。服务器接受用户请求,DispatcherServlet捕获请求。
- 获取处理器执行链。根据配置匹配路径,通过HandlerMapping处理器映射器获取Handler处理器和InterceptorList拦截器列表,封装为HandlerExecutionChain处理器执行链。
- 返回处理器执行链。返回HandlerExecutionChain处理器执行链。
- 获取处理器适配器。根据HandlerExecutionChain处理器执行链中的Handler处理器,匹配HandlerAdapter处理器适配器。
- 返回处理器适配器。返回HandlerAdapter处理器适配器。
- 执行业务方法。使用HandlerAdapter处理器适配器执行Handler处理器对应的业务方法,根据配置将结果封装为ModelAndView模型视图。
- 返回业务结果。返回ModelAndView模型视图。
- 处理视图。判断是否需要解析视图:如果不用解析视图,则直接返回视图;如果需要解析视图,则匹配ViewResolver视图解析器解析视图。
- 返回视图。使用View视图填充Model模型数据,处理响应。
- 响应请求。将响应返回给用户。
详细流程:

2 源码分析
2.1 请求接收
根据web.xml配置文件中的配置,使用DispatcherServlet匹配/请求,所有请求都会经过DispatcherServlet处理。
2.2 准备处理请求
DispatcherServlet继承自FrameworkServlet,FrameworkServlet间接继承自HttpServlet,请求会调用service()方法。
DipatcherServlet没有实现service()方法,所以调用FrameworkServlet的service()方法:
java1 2 3 4 5 6 7 8 9 10 11 12
| protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } }
|
调用HttpServlet的service()方法,根据请求类型调用方法:
java1 2 3 4
| protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doXxx(req, resp); }
|
调用FrameworkServlet的doXxx()方法,准备处理请求:
java1 2 3 4
| protected final void doXxx(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
|
2.3 开始处理请求
调用FrameworkServlet的processRequest()方法,开始处理请求:
java1 2 3 4 5 6 7 8 9 10
| protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); doService(request, response); }
|
调用DispatcherServlet的doService()方法,执行处理请求前的设置:
java1 2 3 4 5 6 7 8 9 10 11 12
| protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); doDispatch(request, response); }
|
调用DispatcherServlet的doDispatch()方法,继续处理请求:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = checkMultipart(request); HandlerExecutionChain mappedHandler = getHandler(processedRequest); HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }
|
2.4 获取处理器执行链
2.4.1 匹配处理器映射器
调用DispatcherServlet的getHandler()方法,获取处理器执行链:
java1 2 3 4 5 6 7 8 9 10 11 12
| protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
|
调用AbstractHandlerMapping的getHandler()方法,获取处理器执行链:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
|
HandlerMapping用于根据请求获取处理器,有多种实现类,需要根据Controller的使用方式判断使用哪个实现类:
- RequestMappingHandlerMapping:基于
@RequestMapping注解配置映射,最常用的映射器。
- BeanNameUrlHandlerMapping:基于Bean名称配置映射,默认自带映射。
- SimpleUrlHandlerMapping:基于URL配置映射,需要显示配置映射,支持集中配置URL映射,支持通配符,支持批量配置。
- 也支持通过实现HandlerMapping接口的方式自定义映射器。
2.4.2 获取处理器
调用AbstractHandlerMethodMapping的getHandlerInternal()方法,获取处理器:
java1 2 3 4 5 6 7 8
| protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); }
|
调用AbstractHandlerMethodMapping的lookupHandlerMethod()方法,根据请求路径获取处理器:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Match bestMatch = matches.get(0); if (matches.size() > 1) { ... } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
|
2.4.3 封装处理器执行链
2.4.3.1 封装普通处理器
调用AbstractHandlerMapping的getHandlerExecutionChain()方法,封装普通处理器执行链:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }
|
2.4.3.2 封装跨域处理器
调用AbstractHandlerMapping的getCorsHandlerExecutionChain()方法,封装跨域处理器执行链:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, @Nullable CorsConfiguration config) { if (CorsUtils.isPreFlightRequest(request)) { HandlerInterceptor[] interceptors = chain.getInterceptors(); return new HandlerExecutionChain(new PreFlightHandler(config), interceptors); } else { chain.addInterceptor(0, new CorsInterceptor(config)); return chain; } }
|
2.5 获取处理器适配器
调用DispatcherServlet的getHandlerAdapter()方法,获取处理器适配器:
java1 2 3 4 5 6 7 8 9 10 11 12
| 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( ... ); }
|
HandlerAdapter用于根据处理器执行业务逻辑,有多种实现类,需要根据Controller的使用方式判断使用哪个实现类:
- RequestMappingHandlerAdapter:支持基于
@RequestMapping注解的使用方式。最常用的适配器。
- HttpRequestHandlerAdapter:支持实现HttpRequestHandler接口的使用方式。
- SimpleControllerHandlerAdapter:支持实现Controller接口的使用方式,早期适配器。
- SimpleServletHandlerAdapter:支持实现Servlet接口的使用方式,早期适配器。
- 也支持通过实现HandlerAdapter接口的方式自定义处理。
2.6 处理请求业务逻辑
调用AbstractHandlerMethodAdapter的handle()方法,处理请求业务逻辑:
java1 2 3 4
| public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
|
调用RequestMappingHandlerAdapter的handleInternal()方法,处理请求业务逻辑:
java1 2 3 4 5 6
| protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { checkRequest(request); return invokeHandlerMethod(request, response, handlerMethod); }
|
调用RequestMappingHandlerAdapter的invokeHandlerMethod()方法,调用实际处理方法:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); invocableMethod.invokeAndHandle(webRequest, mavContainer); return getModelAndView(mavContainer, modelFactory, webRequest); }
|
2.7 处理业务逻辑
2.7.1 执行业务逻辑
调用ServletInvocableHandlerMethod的invokeAndHandle()方法,执行业务逻辑:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if ( ... ) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); }
|
调用HandlerMethodReturnValueHandlerComposite的handleReturnValue()方法,使用返回值处理器处理返回值:
java1 2 3 4 5 6 7 8 9 10
| public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException( ... ); } handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); }
|
调用HandlerMethodReturnValueHandlerComposite的selectHandler()方法,获取返回值处理器:
java1 2 3 4 5 6 7 8 9
| private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (handler.supportsReturnType(returnType)) { return handler; } } return null; }
|
HandlerMethodReturnValueHandler用于根据返回类型处理返回值,有多种实现类,需要根据返回类型判断使用哪个实现类:
- RequestResponseBodyMethodProcessor:支持处理使用
@ResponseBody注解的返回值,用于返回JSON数据。
- HttpEntityMethodProcessor:支持处理返回类型为HttpEntity的返回值,用于返回响应实体。
- ViewNameMethodReturnValueHandler:支持处理返回类型为String的返回值,用于返回视图页面。
- ModelAndViewMethodReturnValueHandler:支持处理返回类型为ModelAndView的返回值,用于返回使用数据的视图页面。
- 也支持通过实现HandlerMethodReturnValueHandler接口的方式自定义处理器。
2.7.2 处理返回值
2.7.2.1 处理视图
调用ViewNameMethodReturnValueHandler的handleReturnValue()方法,处理视图:
java1 2 3 4 5 6 7 8 9 10
| public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { String viewName = returnValue.toString(); mavContainer.setViewName(viewName); if (isRedirectViewName(viewName)) { mavContainer.setRedirectModelScenario(true); } }
|
2.7.2.2 处理JSON数据
调用RequestResponseBodyMethodProcessor的handleReturnValue()方法,处理JSON数据:
java1 2 3 4 5 6 7 8 9 10
| public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }
|
2.7.3 处理模型视图
调用RequestMappingHandlerAdapter的getModelAndView()方法,处理模型视图:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; }
|
2.8 处理视图
2.8.1 准备视图
调用DispatcherServlet的processDispatchResult()方法,处理视图:
java1 2 3 4 5 6 7 8 9 10 11 12 13
| private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { if (exception != null) { ... } if (mv != null && !mv.wasCleared()) { render(mv, request, response); } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
|
调用DispatcherServlet的render()方法,渲染视图:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null) { view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException( ... ); } } else { view = mv.getView(); if (view == null) { throw new ServletException( ... ); } } view.render(mv.getModelInternal(), request, response); }
|
2.8.2 获取视图
2.8.2.1 通过名称获取视图
调用DispatcherServlet的resolveViewName()方法,通过名称获取视图:
java1 2 3 4 5 6 7 8 9 10 11 12
| protected View resolveViewName(String viewName, @Nullable Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { if (this.viewResolvers != null) { for (ViewResolver viewResolver : this.viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { return view; } } } return null; }
|
ViewResolver用于将视图名称解析为视图对象,有多种实现类,需要根据页面的格式判断使用哪个实现类:
- InternalResourceViewResolver:支持解析JSP页面。最常见的解析器。
- BeanNameViewResolver:支持将逻辑视图名解析为Bean对象。
- XmlViewResolver:支持解析XML文件。
- ResourceBundleViewResolver:支持解析属性文件。
- 也支持通过实现ViewResolver接口的方式自定义处理。
2.8.2.2 通过对象获取视图
调用ModelAndView的getView()方法,通过对象获取视图:
java1 2 3 4
| public View getView() { return (this.view instanceof View ? (View) this.view : null); }
|
2.8.3 渲染视图
调用AbstractView的render()方法,渲染视图:
java1 2 3 4 5 6 7 8
| public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); prepareResponse(request, response); renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); }
|
条