在Spring与SpringMVC整合的博客中(https://www.yuque.com/zhanyifan-rkxpe/grf7g5/ei9r2u) 我们提到,最终Spring与SpringMVC整合完成之后,会创建出一个DispatcherServlet,并将他添加到Servlet容器中。都知道,Servlet在处理请求的时候,会调用父类的service()方法,最终调用到doService中。所以,我们就从doService方法开始看起。

DispatcherServlet#doService

其中,最关键是,调用了this.doDispatch(request, response)方法

  1. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. this.logRequest(request);
  3. Map<String, Object> attributesSnapshot = null;
  4. if (WebUtils.isIncludeRequest(request)) {
  5. attributesSnapshot = new HashMap();
  6. Enumeration attrNames = request.getAttributeNames();
  7. label95:
  8. while(true) {
  9. String attrName;
  10. do {
  11. if (!attrNames.hasMoreElements()) {
  12. break label95;
  13. }
  14. attrName = (String)attrNames.nextElement();
  15. } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
  16. attributesSnapshot.put(attrName, request.getAttribute(attrName));
  17. }
  18. }
  19. request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
  20. request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
  21. request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
  22. request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
  23. if (this.flashMapManager != null) {
  24. FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
  25. if (inputFlashMap != null) {
  26. request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
  27. }
  28. request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
  29. request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
  30. }
  31. try {
  32. this.doDispatch(request, response);
  33. } finally {
  34. if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
  35. this.restoreAttributesAfterInclude(request, attributesSnapshot);
  36. }
  37. }
  38. }

doDispatch(request, response)

主要的流程包括如下的几步:

  1. processedRequest = checkMultipart(request) 判断当前的请求是否是上传文件的请求
  2. mappedHandler = getHandler(processedRequest) 根据当前请求,获取到对应的处理器执行链
  3. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()) 根据处理器执行链中的处理器,找到对应的适配器(Handler有多种实现方式,采用适配器的模式进行适配)
  4. mappedHandler.applyPreHandle(processedRequest, response) 调用处理器执行链中的拦截器链的before方法,如果拦截器链全部返回true,则进入第5步,执行目标handler,否则,进去第8步,执行拦截器的afterCompletion方法
  5. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()) 拦截通过,进入处理器执行目标方法,返回ModelAndView
  6. mappedHandler.applyPostHandle(processedRequest, response, mv) 执行处理器执行链中的after方法
  7. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException) 最终,处理执行结果,根据执行结果返回View或者返回json数据。
  8. 如果上面7步,执行中发生了异常,或者执行拦截器返回了false的话,则会执行 triggerAfterCompletion(processedRequest, response, mappedHandler, ex)。执行拦截器的afterCompletion方法

下面,就来分析一波,这几步当中主要做了什么

checkMultipart(request)

检查是否是一个上传文件的请求,如果是,使用multipartResolver 进行request的解析。

getHandler(processedRequest)

通过当前的请求,找到对应的处理器映射器(HandlerMapping),通过对应的HandlerMapping找到对应的处理器执行链
其中getHandlerInternal是一个抽象方法,根据不同的请求,有不同的实现类,例如通过@RequestMapping来实现Controller的话,是采用RequestMappingHandlerMapping来获取对应的Handler等。

  1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2. // 首先呢,根据当前请求,获取到对应的Handler
  3. Object handler = getHandlerInternal(request);
  4. if (handler == null) {
  5. handler = getDefaultHandler();
  6. }
  7. if (handler == null) {
  8. return null;
  9. }
  10. // Bean name or resolved handler?
  11. if (handler instanceof String) {
  12. String handlerName = (String) handler;
  13. handler = obtainApplicationContext().getBean(handlerName);
  14. }
  15. // 然后根据handler以及Reuqest,找出对应的处理器执行链
  16. HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
  17. if (logger.isTraceEnabled()) {
  18. logger.trace("Mapped to " + handler);
  19. }
  20. else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
  21. logger.debug("Mapped to " + executionChain.getHandler());
  22. }
  23. // 处理跨域
  24. if (hasCorsConfigurationSource(handler)) {
  25. CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
  26. CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
  27. config = (config != null ? config.combine(handlerConfig) : handlerConfig);
  28. executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
  29. }
  30. return executionChain;
  31. }

getHandlerAdapter(mappedHandler.getHandler())

根据Servlet启动时,预先加载的处理器适配器,调用supports方法,判断是否适配,如果适配,返回这个适配器

  1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  2. if (this.handlerAdapters != null) {
  3. for (HandlerAdapter adapter : this.handlerAdapters) {
  4. if (adapter.supports(handler)) {
  5. return adapter;
  6. }
  7. }
  8. }
  9. throw new ServletException("No adapter for handler [" + handler +
  10. "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
  11. }

具体的对应关系如下

HttpRequestHandlerAdapter 适配实现了HttpRequestHandler
SimpleControllerHandlerAdapter 适配实现了Controller
AbstractHandlerMethodAdapter 适配标注了@Controller

mappedHandler.applyPreHandle(processedRequest, response)

从头开始循环所有的拦截器,调用其中的preHandle方法,如果其中一个拦截器返回了false,则if条件成立,将会执行triggerAfterCompletion方法,返回false,在doDispatch方法中,将会直接return。

  1. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. HandlerInterceptor[] interceptors = getInterceptors();
  3. if (!ObjectUtils.isEmpty(interceptors)) {
  4. for (int i = 0; i < interceptors.length; i++) {
  5. HandlerInterceptor interceptor = interceptors[i];
  6. if (!interceptor.preHandle(request, response, this.handler)) {
  7. triggerAfterCompletion(request, response, null);
  8. return false;
  9. }
  10. this.interceptorIndex = i;
  11. }
  12. }
  13. return true;
  14. }

ha.handle(processedRequest, response, mappedHandler.getHandler())

调用 getHandlerAdapater 中所返回的处理器适配器中的handle方法,内部

适配器 所调用的方法
HttpRequestHandlerAdapter HttpRequestHandler#handleRequest
SimpleControllerHandlerAdapter Controller#handleRequest
AbstractHandlerMethodAdapter @Controller类中标注了@RequestMapping的方法

mappedHandler.applyPostHandle(processedRequest, response, mv)

调用拦截器的后置方法,这里,采用从后往前遍历的方式,达到一种,类似于递归一样的效果。最先执行preHandle的方法,最后执行postHandle方法。

  1. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
  2. throws Exception {
  3. HandlerInterceptor[] interceptors = getInterceptors();
  4. if (!ObjectUtils.isEmpty(interceptors)) {
  5. for (int i = interceptors.length - 1; i >= 0; i--) {
  6. HandlerInterceptor interceptor = interceptors[i];
  7. interceptor.postHandle(request, response, this.handler, mv);
  8. }
  9. }
  10. }

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException)

处理Handler返回的结果

  1. private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
  2. @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
  3. @Nullable Exception exception) throws Exception {
  4. boolean errorView = false;
  5. if (exception != null) {
  6. if (exception instanceof ModelAndViewDefiningException) {
  7. logger.debug("ModelAndViewDefiningException encountered", exception);
  8. mv = ((ModelAndViewDefiningException) exception).getModelAndView();
  9. }
  10. else {
  11. Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
  12. mv = processHandlerException(request, response, handler, exception);
  13. errorView = (mv != null);
  14. }
  15. }
  16. // 进行视图的渲染,如果ModelAndView不为null的话
  17. // Did the handler return a view to render?
  18. if (mv != null && !mv.wasCleared()) {
  19. // 渲染视图
  20. render(mv, request, response);
  21. if (errorView) {
  22. WebUtils.clearErrorRequestAttributes(request);
  23. }
  24. }
  25. else {
  26. if (logger.isTraceEnabled()) {
  27. logger.trace("No view rendering, null ModelAndView returned.");
  28. }
  29. }
  30. if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  31. // Concurrent handling started during a forward
  32. return;
  33. }
  34. // 最终,调用拦截器的afterCompletion方法
  35. if (mappedHandler != null) {
  36. // Exception (if any) is already handled..
  37. mappedHandler.triggerAfterCompletion(request, response, null);
  38. }
  39. }

render(mv, request, response) ->
view.render(mv.getModelInternal(), request, response) -> AbstractView

  1. @Override
  2. public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
  3. HttpServletResponse response) throws Exception {
  4. if (logger.isDebugEnabled()) {
  5. logger.debug("View " + formatViewName() +
  6. ", model " + (model != null ? model : Collections.emptyMap()) +
  7. (this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
  8. }
  9. // 从Model中获取响应的数据
  10. Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
  11. prepareResponse(request, response);
  12. // 渲染响应的数据
  13. renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
  14. }