摘要:而的類(lèi)型在未來(lái)是極有可能變動(dòng)或繼續(xù)追加的。設(shè)計(jì)者將與關(guān)聯(lián),當(dāng)追加新的類(lèi)型以后,現(xiàn)有代碼并不需要改動(dòng),符合面向?qū)ο蟮挠忠辉瓌t開(kāi)閉原則。處理器適配器與處理器映射器的作用類(lèi)似,都是為了解耦合。優(yōu)秀的程序員是藝術(shù)家,而藝術(shù)就是代碼。
先上一段Spring MVC核心類(lèi)DispatcherServlet中最重要的方法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); // 根據(jù)當(dāng)前請(qǐng)求獲取對(duì)應(yīng)的處理器映射器 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 根據(jù)handler類(lèi)型獲取對(duì)應(yīng)的處理器適配器 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()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we"re processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } 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()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
關(guān)注代碼中打中文注釋的兩個(gè)地方,一個(gè)獲取對(duì)應(yīng)handler的處理器映射器,一個(gè)獲取對(duì)應(yīng)handler的處理器適配器。那為什么需要這兩個(gè)東西,我們直接在handler中寫(xiě)映射邏輯,直接通過(guò)handler來(lái)執(zhí)行處理器方法難道不行嗎?答案是否定的,但Spring為什么要這樣做?有以下幾個(gè)好處
1.將具體的handler與handlerMapping分離開(kāi),為了符合單一職責(zé)
2.讓具體的處理器與DispatcherServlet解耦合,為了符合開(kāi)閉原則
我們知道所有的處理器映射器都有共同的基類(lèi)HandlerMapping,這個(gè)是可以確定的,也是不會(huì)改變的。而handler的類(lèi)型在未來(lái)是極有可能變動(dòng)或繼續(xù)追加的。當(dāng)前版本Spring有以下幾種handler類(lèi)型:
-HandlerMethod(通過(guò)RequestMappingHandlerMapping解析而來(lái),我們最常使用的)
-Servlet(繼承自Servlet接口的處理器)
-Controller(繼承自Controller接口的處理器)
它們之前并沒(méi)有共同的基類(lèi),也不可能有共同的基類(lèi),因?yàn)樗鼈儊?lái)自不同的包,來(lái)自不同的設(shè)計(jì)者。
Spring設(shè)計(jì)者將DispatcherServlet與HandlerMapping關(guān)聯(lián),當(dāng)追加新的handler類(lèi)型以后,現(xiàn)有代碼并不需要改動(dòng),符合面向?qū)ο蟮挠忠辉瓌t:開(kāi)閉原則。
處理器適配器與處理器映射器的作用類(lèi)似,都是為了解耦合。
if(handler instanceof Servlet){ (Servlet)handler.service(); }else if(handler instanceof HandlerMethod){ (ServletInvocableHandlerMethod)handler.invokeAndHandle(); }else if (handler instanceof Controller){ ((Controller) handler).handleRequest(); }
如果我們要新增一種處理器類(lèi)型,必然要繼續(xù)追寫(xiě)else if來(lái)進(jìn)行處理,但使用處理器適配器后,DispatcherServlet不需要改動(dòng)任何代碼,因?yàn)樗灰蕾?lài)HandlerAdapter,這樣DispatcherServlet與具體的Handler就解耦合了,它們之前可以獨(dú)立發(fā)展。
優(yōu)秀的程序員是藝術(shù)家,而藝術(shù)就是代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74843.html
摘要:概述是目前主流的框架之一。這部分的詳細(xì)分析見(jiàn)深入淺出流程解析調(diào)用的具體方法處理請(qǐng)求,并返回一個(gè)。這部分的詳細(xì)分析見(jiàn)深入淺出流程解析視圖解析,遍歷的列表,獲取對(duì)應(yīng)的對(duì)象,入口方法渲染,調(diào)用中獲取的的方法,完成對(duì)數(shù)據(jù)的渲染。 前言 其實(shí)一年前就想系統(tǒng)地記錄下自己閱讀spring源碼的收獲,搞一個(gè)深入淺出spring的系列文章,但是因?yàn)楣ぷ髟颍t遲沒(méi)有下筆。今天終于可以開(kāi)始自己一年前的計(jì)劃...
摘要:?jiǎn)栴}來(lái)了,我們到底還在用嗎答案是,不全用。后者是初始化的配置,主要是的配置。啟動(dòng)類(lèi)測(cè)試啟動(dòng)項(xiàng)目后,在瀏覽器里面輸入。通過(guò)查詢(xún)已裝載的,并且支持該而獲取的。按照前面對(duì)的描述,對(duì)于而言,這個(gè)必定是。的核心在的方法中。 之前已經(jīng)分析過(guò)了Spring的IOC(《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》)與AOP(《從源碼入手,一文帶你讀懂Spring AOP面向切面編程》)的源碼,本次...
摘要:源碼倉(cāng)庫(kù)本文倉(cāng)庫(kù)三層結(jié)構(gòu)表現(xiàn)層模型業(yè)務(wù)層持久層工作流程用戶前端控制器用戶發(fā)送請(qǐng)求前端控制器后端控制器根據(jù)用戶請(qǐng)求查詢(xún)具體控制器后端控制器前端控制器處理后結(jié)果前端控制器視圖視圖渲染視圖前端控制器返回視圖前端控制器用戶響應(yīng)結(jié) SpringMvc 【源碼倉(cāng)庫(kù)】【本文倉(cāng)庫(kù)】 三層結(jié)構(gòu) 表現(xiàn)層 MVC模型 業(yè)務(wù)層 service 持久層 dao 工作流程 用戶->前端控制器:用戶...
摘要:是一個(gè)基于的框架。控制器將視圖響應(yīng)給用戶通過(guò)視圖展示給用戶要的數(shù)據(jù)或處理結(jié)果。有了減少了其它組件之間的耦合度。 相關(guān)閱讀: 本文檔和項(xiàng)目代碼地址:https://github.com/zhisheng17/springmvc 轉(zhuǎn)載請(qǐng)注明出處和保留以上文字! 了解 Spring: Spring 官網(wǎng):http://spring.io/ 一個(gè)好的東西一般都會(huì)有一個(gè)好的文檔解釋說(shuō)明,如果你...
閱讀 595·2021-11-22 14:45
閱讀 3086·2021-10-15 09:41
閱讀 1585·2021-10-11 10:58
閱讀 2807·2021-09-04 16:45
閱讀 2622·2021-09-03 10:45
閱讀 3252·2019-08-30 15:53
閱讀 1234·2019-08-29 12:28
閱讀 2146·2019-08-29 12:14