javascript
SpringMVC运行流程分析
一、運行流程圖
下面是 SpringMVC 運行流程的分析圖,包括了攔截器的調用過程,目標資源的處理以及異常處理。
二、運行流程中的相關組件
在上面的流程圖中有幾個比較重要的組件,下面大概描述一下其對應的作用。
DispatcherServlet:用于接收請求,響應結果。相當于轉發(fā)器,中央處理器。用戶請求到達DispatcherServlet,它是整個流程控制中心,由它調用其它組件來處理用戶的請求,DispatcherServlet 的存在降低了組件之間的耦合性。
HandlerMapping:負責根據用戶請求的URL找到handler路由處理器,SpringMVC 提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,注解方式等。
HandlerAdapter:按照特定的規(guī)則幫助DispatcherServlet去執(zhí)行handler。比如調用帶注釋的控制器需要解析注釋等。
ViewResolver:提供視圖名稱和實際視圖之間的映射。ViewResolver首先根據邏輯視圖名解析成物理視圖名,即具體的頁面地址,再生成View視圖對象,最后對View進行渲染將處理結果通過頁面展示給用戶。
三、源碼分析
運行流程的執(zhí)行通過DispatcherServlet中的doDispatch(HttpServletRequest request, HttpServletResponse response)方法進行統一的調用與管理。
PS:這里只能給大家提供一個調試代碼的方法,其中有很多細節(jié)這里就不再一一描述了。
下面貼出 SpringMVC 4.3.16.RELEASE 版本中 doDispatch() 方法的源代碼。
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);// 在getHandler方法中通過HandlerMapping獲得HandlerExecutionChain對象mappedHandler = getHandler(processedRequest);if (mappedHandler == null || mappedHandler.getHandler() == null) {noHandlerFound(processedRequest, response);return;}// 獲得HandlerAdapter對象HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// 調用攔截器的preHandle()方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 調用目標路由方法得到ModelAndView對象mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);// 調用攔截器的postHandle()方法 mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {dispatchException = new NestedServletException("Handler dispatch failed", err);}/*** 在processDispatchResult() 方法中首先會判斷是否存在異常,然后完成試圖的渲染,* 并調用攔截器的afterCompletion()方法*/processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {if (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}doDispatch(HttpServletRequest request, HttpServletResponse response)方法調用了很多其他的方法來保證運行流程正確的執(zhí)行,對于這些方法具體做了什么,需要你自己通過 DEBUG 的方式去了解。
總結
以上是生活随笔為你收集整理的SpringMVC运行流程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络体系架构—运输层协议概述
- 下一篇: Spring Boot零散知识总结