1. 程式人生 > >spring mvc核心原始碼分析

spring mvc核心原始碼分析

前言

自研究了spring security核心原始碼以來,在實踐使用的基礎上更為深入的學習了它的思想.我的java世界彷彿被打開了一扇大門,開始對研究原始碼有種渴望.打算先看一輪核心原始碼,滿足目前工作需要,待對boot有個整體的瞭解之後再逐個細細研究

spring mvc核心流程圖

流程說明:

  1. 使用者傳送請求到dispatcherServlet,它執行父類frameworkServlet的service方法,service()->processRequest()開始處理請求,processRequest()->doService()->doDispatch();這一段都是給request里加入一些spring的bean,然後處理一下request
  2. dispatcherServlet遍歷自己的handlerMapping,當正確的handlerMapping找到handlerExcutionChain的時候返回,給dispatchServlet.(chain裡主要是一個handlerAdapter和一些攔截器)
  3. handlerExcutionChain開始攔截器處理請求,然後呼叫handlerAdapter裡的handler()方法,handler()->AbstractHandlerMethodAdapter裡的handleInternal(),然後反射執行我們controller裡的業務邏輯,將得到的modelAndView物件返回給dispatchServlet,然後繼續執行攔截器方法.
  4. dispacherServlet  呼叫processDispatchResult把得到的modelAndView交給viewResolve去render檢視

原始碼一覽

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

  2. HttpServletRequest processedRequest = request;

  3. HandlerExecutionChain mappedHandler = null;

  4. boolean multipartRequestParsed = false;

  5. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

  6. try {

  7. try {

  8. ModelAndView mv = null;

  9. Object dispatchException = null;

  10. try {

  11. //是否檔案上傳

  12. processedRequest = this.checkMultipart(request);

  13. multipartRequestParsed = processedRequest != request;

  14.   //獲取handlerExcutionChain

  15. mappedHandler = this.getHandler(processedRequest);

  16. if (mappedHandler == null) {

  17. this.noHandlerFound(processedRequest, response);

  18. return;

  19. }

  20. //獲取handlerAdapter

  21. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

  22. String method = request.getMethod();

  23. boolean isGet = "GET".equals(method);

  24. if (isGet || "HEAD".equals(method)) {

  25. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

  26. if (this.logger.isDebugEnabled()) {

  27. this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);

  28. }

  29. if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {

  30. return;

  31. }

  32. }

  33. //呼叫攔截器們的前置方法

  34. if (!mappedHandler.applyPreHandle(processedRequest, response)) {

  35. return;

  36. }

  37. //呼叫controller裡的業務邏輯方法並返回modelAndView

  38. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

  39. if (asyncManager.isConcurrentHandlingStarted()) {

  40. return;

  41. }

  42. this.applyDefaultViewName(processedRequest, mv);

  43.   //呼叫攔截器的後置方法

  44. mappedHandler.applyPostHandle(processedRequest, response, mv);

  45. } catch (Exception var20) {

  46. dispatchException = var20;

  47. } catch (Throwable var21) {

  48. dispatchException = new NestedServletException("Handler dispatch failed", var21);

  49. }

  50. //把modelAndView交給viewResolver去render檢視

  51. this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

  52. } catch (Exception var22) {

  53. this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);

  54. } catch (Throwable var23) {

  55. this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));

  56. }

  57. } finally {

  58. if (asyncManager.isConcurrentHandlingStarted()) {

  59. if (mappedHandler != null) {

  60. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

  61. }

  62. } else if (multipartRequestParsed) {

  63. this.cleanupMultipart(processedRequest);

  64. }

  65. }

  66. }

  1. 獲取handlerExcutionChain物件

  2. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

  3. if (this.handlerMappings != null) {

  4. Iterator var2 = this.handlerMappings.iterator();

  5. while(var2.hasNext()) {

  6. HandlerMapping hm = (HandlerMapping)var2.next();

  7. if (this.logger.isTraceEnabled()) {

  8. this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");

  9. }

  10. HandlerExecutionChain handler = hm.getHandler(request);

  11. if (handler != null) {

  12. return handler;

  13. }

  14. }

  15. }

呼叫攔截器的前置方法

  1. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {

  2. HandlerInterceptor[] interceptors = this.getInterceptors();

  3. if (!ObjectUtils.isEmpty(interceptors)) {

  4. for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {

  5. HandlerInterceptor interceptor = interceptors[i];

  6. if (!interceptor.preHandle(request, response, this.handler)) {

  7. this.triggerAfterCompletion(request, response, (Exception)null);

  8. return false;

  9. }

  10. }

  11. }

  12. return true;

  13. }

//攔截器的後置方法

  1. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {

  2. HandlerInterceptor[] interceptors = this.getInterceptors();

  3. if (!ObjectUtils.isEmpty(interceptors)) {

  4. for(int i = interceptors.length - 1; i >= 0; --i) {

  5. HandlerInterceptor interceptor = interceptors[i];

  6. interceptor.postHandle(request, response, this.handler, mv);

  7. }

  8. }

  9. }

反射controller我們寫的邏輯

  1. protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

  2. this.checkRequest(request);

  3. ModelAndView mav;

  4. if (this.synchronizeOnSession) {

  5. HttpSession session = request.getSession(false);

  6. if (session != null) {

  7. Object mutex = WebUtils.getSessionMutex(session);

  8. synchronized(mutex) {

  9. mav = this.invokeHandlerMethod(request, response, handlerMethod);

  10. }

  11. } else {

  12. mav = this.invokeHandlerMethod(request, response, handlerMethod);

  13. }

  14. } else {

  15. mav = this.invokeHandlerMethod(request, response, handlerMethod);

  16. }

  17. if (!response.containsHeader("Cache-Control")) {

  18. if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {

  19. this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);

  20. } else {

  21. this.prepareResponse(response);

  22. }

  23. }

  24. return mav;

  25. }

檢視渲染

  1. private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {

  2. boolean errorView = false;

  3. if (exception != null) {

  4. if (exception instanceof ModelAndViewDefiningException) {

  5. this.logger.debug("ModelAndViewDefiningException encountered", exception);

  6. mv = ((ModelAndViewDefiningException)exception).getModelAndView();

  7. } else {

  8. Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;

  9. mv = this.processHandlerException(request, response, handler, exception);

  10. errorView = mv != null;

  11. }

  12. }

  13. if (mv != null && !mv.wasCleared()) {

  14. this.render(mv, request, response);

  15. if (errorView) {

  16. WebUtils.clearErrorRequestAttributes(request);

  17. }

  18. } else if (this.logger.isDebugEnabled()) {

  19. this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");

  20. }

  21. if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

  22. if (mappedHandler != null) {

  23. mappedHandler.triggerAfterCompletion(request, response, (Exception)null);

  24. }

  25. }

  26. }

總結

springmvc核心並不複雜,主要是圍繞dispatcherServlet,請朋友們自動動手debugger,這樣學習才會更有效