spring mvc解读
上篇自己手写了了一下mvc的简易版,这次解读一下springmvc官方源码,先大概根据图片来了解一下流程

debug准备:实现debug的具体流程,创建springboot项目,添加web依赖,编写controller类,完成以上流程找到DispatcherServlet类(org.springframework.web.servlet包下),该类继承FrameworkServlet(抽象类),FrameworkServlet继承HttpServletBean,HttpServletBean继承HttpServlet;根据servlet的实现,肯定先执行init,找到该方法,init方法被重写了

可以看到调用了父类的init,父亲类是GenericServlet,GenericServlet和HttpServlet属于不属于springmvc包下先不讨论,但这个初始化过程还是要知道什么时候开始的;
回到DispatcherServlet,里面重要的组件,与上面对应上了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private MultipartResolver multipartResolver; @Nullable private LocaleResolver localeResolver; /** @deprecated */ @Deprecated @Nullable private ThemeResolver themeResolver; @Nullable private List<HandlerMapping> handlerMappings; @Nullable private List<HandlerAdapter> handlerAdapters; @Nullable private List<HandlerExceptionResolver> handlerExceptionResolvers; @Nullable private RequestToViewNameTranslator viewNameTranslator; @Nullable private FlashMapManager flashMapManager; @Nullable private List<ViewResolver> viewResolvers;
|
先来看两个构造方法,第一个构造方法打上断点
1 2 3 4 5 6 7 8
| public DispatcherServlet() { this.setDispatchOptionsRequest(true); }
public DispatcherServlet(WebApplicationContext webApplicationContext) { super(webApplicationContext); this.setDispatchOptionsRequest(true); }
|
往下走,可以看到执行到,
这个自动配置,这里返回的就是我们今天要讨论的DispatcherServlet;写一个发送post请求的servlet,回到HttpServlet类,给doPost打上断点,postman发送请求,会发生什么,可以看到请求的一瞬间,进入debug,执行下一步就进入FrameworkServlet的doPost,执行processRequest方法

执行完毕后,走到DispatcherServlet的doDispatch方法,这里就是sprmvc执行的具体流程了。
1 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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; // 提供组件异步处理 HTTP 请求 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try { try { ModelAndView mv = null; Exception dispatchException = null;
try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; }
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = HttpMethod.GET.matches(method); if (isGet || HttpMethod.HEAD.matches(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } }
if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; }
this.applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new ServletException("Handler dispatch failed: " + var21, var21); }
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { triggerAfterCompletion(processedRequest, response, mappedHandler, new ServletException("Handler processing failed: " + var23, var23)); }
} finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); }
asyncManager.setMultipartRequestParsed(multipartRequestParsed); } else if (multipartRequestParsed || asyncManager.isMultipartRequestParsed()) { this.cleanupMultipart(processedRequest); }
} }
|
根据上图
1.第一步请求进入DispatcherServlet
2.获取Handler,返回HandlerExecutionChain,包括

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| mappedHandler = this.getHandler(processedRequest);
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { Iterator var2 = this.handlerMappings.iterator();
while(var2.hasNext()) { HandlerMapping mapping = (HandlerMapping)var2.next(); HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } }
|
3 .根据返回来的Handler来寻找HandlerAdapter,继续走
1
| HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
|
4 . HandlerAdapter处理解析到的Handler
1
| mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
|
5.6.看作一步,handle方法内部,HandlerAdapter是一个接口

7 返回modelview(这里的属性名为mv)
1 2 3 4
| // 用于给模型和视图(ModelAndView)对象mv应用默认的视图名称 this.applyDefaultViewName(processedRequest, mv); // 用于执行所有后置拦截器(Interceptor)的postHandle方法 mappedHandler.applyPostHandle(processedRequest, response, mv);
|
8 9 10 可以看成一步
1 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 35 36 37 38 39 40 41 42 43 44
| this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { ModelAndViewDefiningException mavDefiningException = (ModelAndViewDefiningException)exception; this.logger.debug("ModelAndViewDefiningException encountered", exception); mv = mavDefiningException.getModelAndView(); } else { Object handler = mappedHandler != null ? mappedHandler.getHandler() : null; mv = this.processHandlerException(request, response, handler, exception); errorView = mv != null; } }
if (mv != null && !mv.wasCleared()) { this.render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else if (this.logger.isTraceEnabled()) { this.logger.trace("No view rendering, null ModelAndView returned."); }
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, (Exception)null); }
} }
protected LocaleContext buildLocaleContext(final HttpServletRequest request) { LocaleResolver lr = this.localeResolver; if (lr instanceof LocaleContextResolver localeContextResolver) { return localeContextResolver.resolveLocaleContext(request); } else { return () -> { return lr != null ? lr.resolveLocale(request) : request.getLocale(); }; } }
|
可以看到这里对视图有好几种处理方式(异常,无视图,有视图),现在我们都是前后端分离,返回json,这种属于无视图的处理,有视图的话也是利用response流处理液乳到视图上,没有是直接放回response流;

现在都是springboot,springboot自动配置处理了DispatcherServlet,如下
