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