核心:前端控制器:DispatcherServlet前端
功能:MVC設計模式中的Controller角色,掌控全局web
本質是將DispatcherServlet及關聯的Spring上下文環境的初始化工做織入Servlet的生命週期內,將外部WEB請求轉換爲Spring Bean能處理的形式,而後將處理後的結果藉助於符合J2EE規範組件,呈現給客戶端。spring
HttpServletBean: init(),內部調用initServletBean完成Servlet的初始化設計模式
FrameworkServlet 重寫 initServletBean()方法,方法內部調用 initWebApplicationContext()方法完成與DispatcherServlet關聯的web應用上下文的初始化工做,應用環境的基礎環境的初始化工做由子類DispatcherServlet的onRefresh方法完成。tomcat
DispatcherServlet.onRefresh方法內部調用:initStrategies方法完成Springmvc須要的各類組件的初始化工做,至此springmvc可提供完整的外部應用訪問功能。mvc
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
springmvc 默認配置文件:DispatcherServlet.propertiesapp
核心方法:doService,本質是對Serlvet接口的service方法的最終實現。async
doService:完成應用請求的數據封裝封裝,內部調用doDispatch方法完成請求調度調度處理源碼分析
源碼分析:post
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //判斷外部請求是不是多部分請求(通常用於文件上傳) processedRequest = checkMultipart(request); multipartRequestParsed = processedRequest != request; // 根據請求請求獲取請求處理器:注意這裏會返回對應的處理器以及潛在的攔截器 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 獲取可以支持請求處理器的處理器適配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //前置攔截器攔截請求 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { // 處理器適配器將請求傳遞給控制器處理,獲取ModelView對象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { if (asyncManager.isConcurrentHandlingStarted()) { return; } } //設置視圖名 applyDefaultViewName(request, mv); //後置攔截器攔截請求 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //處理控制器返回的結果ModelAndView,主要是講model的數據填充view,渲染後將數據返回給客戶端顯示 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); return; } // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } }
主要是將MappingHandler返回的ModelAndView種的Model數據填充到view,並藉助於servlet容器(例如tomcat)呈現給客戶端。
AbstractView. render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response): //具體執行代碼 renderMergedOutputModel(mergedModel, request, response);
案例分析:內部資源視圖(例JSP) InternalResourceView. renderMergedOutputModel
protected void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { //封裝客戶端可視的請求資源數據 HttpServletRequest requestToExpose = getRequestToExpose(request); exposeModelAsRequestAttributes(model, requestToExpose); //客戶端請求添加輔助信息 exposeHelpers(requestToExpose); // 獲取請求轉發路徑 String dispatcherPath = prepareForRendering(requestToExpose, response); //獲取目標資源的請求調度器 RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath); if (rd == null) { throw new ServletException("Could not get RequestDispatcher for [" + getUrl() + "]: Check that the corresponding file exists within your web application archive!"); } //若是一個URL的內部請求則進行響應資源追加,例如網頁內的圖片連接等 if (useInclude(requestToExpose, response)) { response.setContentType(getContentType()); if (logger.isDebugEnabled()) { logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'"); } rd.include(requestToExpose, response); } else { // Note: The forwarded resource is supposed to determine the content type itself. if (logger.isDebugEnabled()) { logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'"); } //repuest請求轉發,說明springmvc採用的轉發而不是重定向的方式 rd.forward(requestToExpose, response); } }