dispatcherServlet做爲前端控制器的主要做用就是接受請求與處理響應。前端
不過它不是傳統意義上的servlet,它在接受到請求後採用轉發的方式,將具體工做交給專業人士去作。json
參與角色主要有:mvc
前端控制器(DispatcherServlet)app
處理映射器(HandlerMapping)jsp
處理適配器(HandlerAdapter)async
處理器((Handler)Controller)ide
視圖解析器(ViewReslover)ui
視圖(View)this
(找了一張圖,把請求過程與步驟清晰的呈現了出來)url
第一步:前端控制器dispatcher接受請求
Client---url--->Dispatcher
第二步:前端控制器去發起handler映射查找請求
Dispatcher---HttpServletRequest---> HandlerMapping
第三步:處理器映射器查找hanlder並返回HandlerExetuionChain
Dispatcher <---HandlerExeutionChain---HandlerMapping
第四步:前端控制器發起請求處理器適配器請求執行
Dispatcher---Handler---> HandlerAdapter
第五步:處理器適配器去調用handler執行
HandlerAdapter---HttpServletRequest> Handler(Controller)
第六步:處理器處理後返回ModelAndView給HandlerAdapter
HandlerAdapter <---ModelAndView---Handler(Controller)
第七步:處理器適配器將ModelAndView返回給前端控制器
Dispatcher <---ModelAndView---HandlerAdapter
第八步:前端控制器請求視圖解析器解析ModelAndView
Dispatcher---ModelAndView---> ViewReslover
第九步:視圖解析器解析視圖後返回視圖View給前端控制器
Dispatcher <---View---ViewReslover
第十步:前端控制器請求視圖要求渲染視圖
Dispatcher--->View--->render
第十一步:前端控制器返回響應
Response <---Dispatcher
源碼探祕
咱們能夠來看看DispatcherServlet的繼承結構
其實DispatcherServlet能處理請求是由於HttpServlet類的service方法,而HttpServlet又來自Servlet接口定義的規範。
能夠看到抽象類HttpServlet實現了接口Servlet的service方法,根據請求類型不一樣執行了不一樣的方法(doGet,doPost)
當請進來後,由HttpServlet的子類FrameworkServlet重寫的service方法執行請求,能夠看到437行子類調用了父類的service方法,而後在父類執行doGet之類的方法時,因爲子類FrameworkServlet重寫了父類方法,交由子類執行,因此進到了個人doGet斷點裏面,它調用了處理請求方法。
接下來咱們看看Proce***equest方法的源碼
1 protected final void proce***equest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 long startTime = System.currentTimeMillis(); 3 Throwable failureCause = null; 4 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 5 LocaleContext localeContext = this.buildLocaleContext(request); 6 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); 7 ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); 8 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 9 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor(null)); 10 this.initContextHolders(request, localeContext, requestAttributes); 11 12 try { 13 this.doService(request, response); 14 } catch (IOException | ServletException var16) { 15 failureCause = var16; 16 throw var16; 17 } catch (Throwable var17) { 18 failureCause = var17; 19 throw new NestedServletException("Request processing failed", var17); 20 } finally { 21 this.resetContextHolders(request, previousLocaleContext, previousAttributes); 22 if (requestAttributes != null) { 23 requestAttributes.requestCompleted(); 24 } 25 26 this.logResult(request, response, (Throwable)failureCause, asyncManager); 27 this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); 28 } 29 30 }
前面一系列初始化工做咱們先無論,看看重要的部分,try裏面的doService方法
跟蹤進去看了一下,因爲它是抽象方法,因此會由子類實現和執行,也就是咱們的DispatchServlet類了
1protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 this.logRequest(request); 3 Map
因此第一步也就完成了,第一步的任務就是走進這裏來。
Dispatcher---HttpServletRequest---> HandlerMapping
上面的源碼中主要工做就是給request實例設置一系列參數,要注意的就是doDispatch方法,這裏面就是mvc的核心了,前面第一張交互圖裏面的流程都是在這裏實現的。
能夠看到,經過HttpRequestServlet做爲參數請求handlerMapping
Dispatcher <---HandlerExeutionChain---HandlerMapping
能夠看到上圖中返回了mappedHandler變量,就是HandlerExtuceChain類型
能夠看到,已經找到並返回了咱們的HomeController處理器(Hanlder)
Dispatcher---Handler---> HandlerAdapter
從508行能夠看到,適配器傳入handler對象和reaquest等信息,執行handler()方法
HandlerAdapter---HttpServletRequest> Handler(Controller)
從這裏能夠看到,調用的handlerInternal是個抽象方法,會調用子類的實現方法,子類由RequestMappingHandlerAdapter實現,這個類也是咱們常常在xml裏面配置的類
經過invokeHandlerMethod方法執行進到controller裏面
方法執行後返回咱們的index
HandlerAdapter <---ModelAndView---Handler(Controller)
經過調用invokeHandlerMethod方法返回ModelAndView
Dispatcher <---ModelAndView---HandlerAdapter
Dispatcher---ModelAndView---> ViewReslover
Dispatcher <---View---ViewReslover
能夠看到,返回的視圖,url指向index.jsp頁面
Dispatcher--->View--->render
若是View對象不爲空,將會調用render方法渲染
若是返回的是json對象,屬於接口的,是不會走這裏的
此時會找對應的視圖解析器去渲染
裏面其實也沒幹啥,就作了個跳轉,到jsp頁面去綁定數據
Response <---Dispatcher
到這裏也就基本上完了。
處理請求完成後作了個重置工做,而後發佈一個事件,你能夠選擇監聽這個事件,作相應處理。
再看看response裏面
這個就是咱們頁面上的內容了。