<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    對Spring MVC Framework的理解

    Posted on 2005-05-27 11:29 李嵐 閱讀(3320) 評論(3)  編輯  收藏 所屬分類: Java

    前言

    最近在看Spring MVC的源碼,就把自己對MVC模式和對各種框架的實現的認識寫出來給大家看看,算是一個總結.所以,懇請大家用懷疑的眼光來看待這篇文章,假如有認識不對的地方,麻煩指出.

    MVCWEB應用

    MVC是什么就不用我多說了.對于現有較成熟的Model-View-Control(MVC)框架而言,其注意的主要問題無外乎下面這些:

    Model:

    模型應該包含由視圖顯示的數據.J2EE Web應用中,數據通常應該由普通的javabean組成.一旦一個控制器選擇了視圖,模型就要包含視圖相應的數據.模型本身不應該進一步的訪問數據,也不應該和業務對象相聯系.

    模型要解決的問題包括:

    l          封裝要顯示的數據

    l          我不認為模型要依賴于特定的框架

    l          不一定非得是javabean

    View:

    視圖負責顯示出模型包含的信息,視圖不必了解控制器或是底層業務對象的具體實現

    視圖要解決的問題包括:

    l          在顯示給定數據模型的情況下顯示內容

    l          不應該包含有業務邏輯

    l          可能需要執行顯示邏輯,比如顏色交替的顯示某個數組的各行

    l          視圖最好不處理驗證的錯誤,數據的驗證應該在由其他組件完成

    l          視圖不應該處理參數,參數應該交由控制器集中處理

    Control:

    控制器就好像MVC里的中樞神經,它也許會需要一些助手來幫助它比如解析視圖,解析參數等.控制器可以訪問到業務對象或者是它的代理是很重要的,比如Struts里的Action.

    控制器要解決的問題包括:

    l          檢查和抽取請求參數

    l          調用業務對象,傳遞從請求中獲取的參數

    l          創建模型,視圖講顯示對應的模型

    l          選擇一個合適的視圖發送給客戶端

    l          控制器有時不會只有一個

    現有的框架

    現在已經有很多的MVC的框架實現.比較流行的應該就是StrutsWebwork

    Struts

    這是最流行的web框架,幾乎成為了實際上的工業標準.除了上面討論的MVC模式應該有的優點以外.它還有如下一些缺點:

    l          每個Action只生成一次,然后就被緩存起來,再次請求這個Action的時候就不會生成新的對象,而是重復使用第一次生成的對象,這就意味著每個Action必須是線程安全的

    l          采用ActionForm封裝了表單數據,但是卻只能對應String類型的數據, 雖然它可以使用工具Commons Beanutils進行類型轉化,但是僅僅是提供了對象級別的支持

    l          嚴重的依賴于Servlet API, 測試比較困難(不過下一版Struts里的Action.execute的方法簽名講會換成execute(ActionContext actionContext),依賴也許不會那么嚴重)

    l          框架本身的驗證規則比較簡單,一般都是依賴于Commons Validation進行驗證

    l          想在Action前后做些處理很困難.有時甚至不得不自己去寫專門的控制器

    l          由于Struts都是具體的類繼承,這樣很容易打破封裝?

    l          提供各式各樣的自定義的標簽,但是數據綁定太原始了,這樣就使頁面代碼依賴于Struts這個特定的框架,而它卻不是規范,我覺得這是很致命的

    l          它太面向JSP,盡管使用其他視圖技術是有可能的,但是使用的時候卻不是很方便

    Webwork

    這個框架雖然我沒使用過,但是卻一直在關注它的發展

     

    Webwork的設計思想采用了比Struts更為聰明的一種方式,就技術角度上說比Struts要高出不少.它以Command模式為基礎.分為XworkWebwork,而且框架并不依賴于Servlet API.

     

    Xwork提供了很多核心功能:攔截器(Interceptor,運行時表單驗證,類型轉換,IoC容器等.

     

    WebWork建立在Xwork之上,用于處理基于HTTP的響應和請求.MapActionContext封裝了Session,Application等這些Servlet對象.從而解除了和Servlet API的耦合.

     

    但是它仍然不是完美的:

    l          為每一個請求都創建一個Action可能有些浪費.(但是Servlet引擎也是為每個請求創建多個對象,但是也沒看出來對性能有多大的影響?)

    l          當項目越來越大的時候,配置文件可能會很零亂.好像它不支持多個配置文件

    l          異常處理是Command模式里值得注意的問題:我們不知道某一特定命令可能會拋出什么特定的異常,所以execute()被迫拋出異常,而不論異常是運行時異常,還是已檢查異常

     Spring MVC Framework的目標

    上面說了一些MVC的原理,以及現在主流框架的一些問題,現在來看Spring是如何處理的. Spring MVC框架根據不同的角色定義了很多接口,但是它最大的問題也是依賴于Servlet API

    Spring MVC Framework有這樣一些特點:

    l          它是基于組件技術的.全部的應用對象,無論控制器和視圖,還是業務對象之類的都是java組件.并且和Spring提供的其他基礎結構緊密集成.

    l          不依賴于Servlet API(目標雖是如此,但是在實現的時候確實是依賴于Servlet)

    l          可以任意使用各種視圖技術,而不僅僅局限于JSP

    l          支持各種請求資源的映射策略

    l          它應是易于擴展的

    我認為評價一個框架,應該有幾個原則

    l          它應該是易于使用的,易于測試的

    Spring 易于使用嗎?我不這么覺得,尤其是它的配置文件.在最恐怖的情況下,各種業務邏輯,基礎設施也許會擁擠在一個配置文件里.而如事務處理這些基礎設施應該是由容器管理而不是開發人員,就算把這些分開到幾個配置文件里,邏輯上雖然清晰了,但是基礎設置卻還是暴露在外邊

    Spring易于測試嗎?Spring進行單元測試很容易,測試起來很方便

    l          應該在多個層次上提供接口

    Spring提供了很多接口,而幾乎每個接口都有默認的抽象實現,每個抽象實現都有一些具體實現,所以在可擴展性這點上Spring無疑是很優秀的

    l          框架內部和框架外部應該被區別對待

    框架內部可以很復雜,但是使用起來一定要簡單,Spring的內部比較麻煩,但是它很好的隱藏了這種復雜性,使用起來很舒服,比如設置一個bean的屬性.僅僅是setPropertyValue(String propertyName, Object value)就完成,至于怎么去設置,Spring完全隱藏了這種復雜性

    l          完善的文檔和測試集

    這個就不用說了,老外的東西,都很完善

     Spring Web框架基本流程

    知道了Spring MVC框架,現在來看看它的流程

    Spring MVC Framework大至流程如下:

    web程序啟動的時候,ContextLoaderServlet會把對應的配置文件信息讀取出來,通過注射去初始化控制器DispatchServlet. 而當接受到一個HTTP請求的時候, DispatchServlet會讓HandlerMapping去處理這個請求.HandlerMapping根據請求URL(不一定非要是URL,完全可以自定義,非常靈活)來選擇一個Controller. 然后DispatchServlet會在調用選定的ControllerhandlerRequest方法,并且在這個方法前后調用這個Controllerinterceptor(假如有配置的話),然后返回一個視圖和模型的集合ModelAndView.框架通過ViewResolver來解析視圖并且返回一個View對象,最后調用Viewrender方法返回到客戶端

    DispatcherServlet

    這是框架的控制器,是一個具體類,它通過運行時的上下文對象來初始化.控制器本身并不去控制流程,而只是是Controller控制器”,他只是把處理請求的責任委托給了對應的Controller.

     

    控制器繼承自抽象基類FrameworkServlet,它的屬性webApplicationContext就代表著這個web程序上下文,而這個上下文對象默認實現就是從一個XML文件讀取配置信息(當然也可以是其他文件格式). WebApplicationContext其實是beans包的東西,這個包提供了這個Spring整個框架的基礎結構,以后我會分析這個包的內容.但是現在僅僅需要知道WebApplicationContext代表一個web應用的上下文對象.

     

    現在來看看DispatchServlet是如何工作的:

    DispatchServlet由于繼承自抽象基類FrameworkServlet,FrameworkServlet里的doGet(),doPost()方法里有調用serviceWrapper(),跳到serviceWrapper()里去看,結果發現它有把具體實現委托給了doService(request, response); 方法.所以現在已經很清楚了, DispatchServlet真正實現功能的是doService() 這個方法.

     

    特別的, FrameworkServletinitFrameworkServlet()這個方法是控制器的初始化方法,用來初始化HandlerMappings之類的對象,這也是延遲到子類實現的.其實就是一個Template模式的實現.don’t call us, we will call u.總的看來,Spring就是通過這樣來實現它的控制反轉的:用框架來控制流程,而不是用戶

     

    跳到doService()一看究竟,就會發現真正工作的又是另一個助手函數doDispatch(request, response),沒辦法,繼續看下去,發現這樣兩行代碼

    HandlerExecutionChain mappedHandler = null;

             mappedHandler = getHandler(processedRequest, false);

    HandlerExecutionChain源碼就發現它其實就是對Controller和它的Interceptors的進行了包裝;

     

    getHandler()就是從HandlerMappings(這是一個List,存放的handlerMapping對象)中取出對應的handlerMapping對象, 每個HandlerMapping對象代表一個ControllerURL的映射(其實在運行的時候是一個HandlerExecutionChainURL的映射,HandlerExecutionChain對象其實就是對Controller和它interceptors的一個包裝器,可以把HandlerMapping看成ControllerURL的映射).而這個HandlerMapping是通過配置文件在運行時注射進來的,一般是SimpleUrlHandlerMapping這個子類

     

    取得了HandlerMapping對象,繼續向下看,發現:

                      if (mappedHandler.getInterceptors() != null) {

                                                   for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {

                                                            HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];

                                                            if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {

                                                                     triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

                                                                     return;

                                                            }

                                                            interceptorIndex = i;

                                                   }

                                         }

    這里就是在調用Controller的攔截器,原理就是這句了:

             interceptor.preHandle(processedRequest, response, mappedHandler.getHandler(), mv);

    preHandle方法傳入了mappedHandler.getHandler()這個參數來實現遞歸調用! interceptor.postHandle方法如此一般.只不過這個方法是在handleRequest方法后調用

     

    繼續看下去:

             HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

    發現ControllerhandleRequest真正的操作又被代理給了HandlerAdapterhandle方法,并且返回一個ModelAndView,我想這里增加一層的意義應該是為了解除ControllerDispatchServlet的耦合吧.

     

    接著就很簡單了,調用render()方法,在這個方法里面由ViewResoler解析出視圖名,再調用視圖對象的render方法把合適的視圖展現給用戶

     

    到此,控制器的流程就OVER

    HandlerMapping

    通過使用HandlerMapping,控制器可以用URL和某一個Controller進行標準的映射,而實現URL映射的具體子類的UrlHandlerMapping.

     

    Spring還允許我們自定義映射,比如通過Session,cookie或者用戶狀態來映射.而這一切僅僅只需要實現HandlerMapping接口而已.不過URL映射已經能滿足大部分的要求

    Controller

    Controller 類似StructsAction, Controller接口只有一個方法handleRequest(),放回一個ModelAndView對象,如同設計目標所說的那樣,每個Controller都是一個java組件,所以它可以在上下文環境中任意配置,組件屬性都會在初始化的時候被配置.Spring自己提供了幾個具體的實現.方便我們使用

    ViewResolver

    Controller通常返回包含視圖名字而不是視圖對象的ModelAndView對象.從而徹底的解除了控制器和視圖之間的耦合關系,并且在這里還可以提供國際化的支持.

    在你的配置文件中你可以:

    welcomeView.class = org.springframework.web.servlet.view. InternalResourceView

    welcomeView.url=/welcome.jsp

    也可以

    welcomeView.class = org.springframework.web.servlet.view.xslt. XsltView

    welcomeView.url=/xslt/default.xslt

     

    View

    這也是一個java組件,它不做任何請求處理或是業務邏輯,它僅僅獲取模型傳遞的數據,并把數據顯示出來.它里面的 render方法按照如下流程工作:

    l          設置模型的數據到request作用域

    l          取得視圖的URL

    l          轉發到對應的URL

    總結:

    Springweb框架是一個很優秀的框架,在這里只是走馬觀花的分析了Spring的工作流程和一些關鍵的類,但是并沒有去深入的去探討它背后所體現的思想,還有它的優缺點等東西.這些都等下次再說吧

     

    這里再次說明一下,上面說的只是我自己的想法,假如有不理解或者不正確的地方,請在下面留言指出或者查看官方的<Spring-Reference>,以后會逐漸推出自己對Spring其他的理解

    Feedback

    # re: 對Spring MVC Framework的理解  回復  更多評論   

    2005-11-10 12:40 by pesome
    寫的很不錯啊,我現在才開始學spring

    # re: 對Spring MVC Framework的理解  回復  更多評論   

    2006-04-03 16:35 by 朱吉赟
    你依然那么蒸蒸日上。

    我手機丟了,QQ密碼忘了,差點與世隔絕了。

    你最近怎么樣?

    我的新QQ:85604123

    # re: 對Spring MVC Framework的理解  回復  更多評論   

    2008-01-11 11:39 by bizairshop
    看來spring mvc不是我的理想框架 航服推薦 http://www.bizairshop.com

    # re: 對Spring MVC Framework的理解  回復  更多評論   

    2013-05-28 14:03 by JAVA22222
    看來spring mvc不是我的理想框架

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    posts - 7, comments - 23, trackbacks - 0, articles - 0

    Copyright © 李嵐

    主站蜘蛛池模板: 亚洲精品国产成人| aⅴ免费在线观看| 亚洲欧美日韩中文字幕一区二区三区 | 豆国产96在线|亚洲| 亚洲一区中文字幕久久| 国产亚洲精aa成人网站| 日本免费一二区在线电影| 亚洲最大免费视频网| 两个人看的www免费视频中文 | 四虎成人精品在永久免费| 国产免费的野战视频| 免费人成激情视频在线观看冫 | 亚洲av手机在线观看| 在线免费观看中文字幕| 国内精品免费麻豆网站91麻豆| 久久大香伊焦在人线免费| 国产精品无码免费专区午夜| 色偷偷亚洲第一综合| 亚洲欧洲无卡二区视頻| 国产成人精品亚洲日本在线| 亚洲视频在线不卡| 18亚洲男同志videos网站| 亚洲av日韩av激情亚洲| 亚洲免费观看视频| 亚洲一区二区三区偷拍女厕| 久久激情亚洲精品无码?V| 亚洲片一区二区三区| 精品亚洲一区二区三区在线播放| 日韩亚洲精品福利| 一本色道久久88综合亚洲精品高清| 国产一区二区免费在线| 亚洲国产精品尤物yw在线| 亚洲成A人片在线观看无码3D| 夜色阁亚洲一区二区三区| 亚洲成人一区二区| 亚洲国产成人影院播放| 亚洲欧洲精品成人久久曰影片 | 爱情岛亚洲论坛在线观看 | 亚洲AV蜜桃永久无码精品| 深夜国产福利99亚洲视频| 亚洲爽爽一区二区三区|