posts - 176, comments - 240, trackbacks - 0, articles - 7

          [導入]jsplet:對Model 2模式的批判

          Posted on 2005-11-15 12:31 canonical 閱讀(350) 評論(1)  編輯  收藏 所屬分類: Witrix開發平臺

             在Jsp Model 2模型中, 用戶的所有請求提交給Controller Servlet, 由Controller進行統一分配, 并且采用推的方式將不同的UI顯示給用戶。 這種推方式在很多人看來是一種優點,因為在Struts等MVC實現中具體推送的UI可以在配置文件中配置,配置完成后還可以通過一些可視化分析工具得到 整個站點地圖。在Model2模式中基本的訪問格式為:
                 action.do?其他參數  

          我 本人從未應用過Model2模式,但與我們的jsplet框架對比,我認為這種推送方式在大多數情況下并不是什么優點。如果將一次web訪問看作是一次函 數調用,則按照Model2模式,這個函數的返回情況是不確定的,需要由一個額外的配置文件來確定。而我們知道,一個返回情況不確定的函數一般不是什么良 好的設計。在我們的框架設計中,一個基本的觀點是盡量將自由度暴露給實際控制它的人。實際上,在大多數情況下,頁面編制人員知道應該使用哪個頁面來顯示數 據,他們并不需要一個額外的配置文件。Jsplet使用如下的url格式:
                 視圖jsp?objectName=模型對象名&objectEvent=響應事件名&其他參數
          舉一個具體的例子:
            
          http://my.com/demo_view.jsp?objectName=/@Demo&objectEvent=test

          demo_view.jsp是指定的顯示頁面, 其代碼如下:
          [code]
          <%@ include file = "/engine.jsp" %>
          <!-- 相當于在jsp模型中增加了一個新的變量thisObj,從而實現jsp頁面的對象化 -->
          <c:out>${thisObj.testVar}</c:out>
          [/code]
          objectName被WebEngine映射到session中的一個對象,在demo_view.jsp中成為thisObj這個變量,這就相當于java語言中的this指針,從而實現了jsp頁面的對象化。

          WebEngine還將objectEvent映射到一個Action響應函數并自動調用它,具體的Action代碼寫在一個獨立的java文件或者jsp文件中。
          DemoAction.jsp
          [code]
          <%@ include file = "/jsp_action_begin.jsp" %>
          <%!
              //
           // objectName映射為thisObj, objectEvent=test映射對actTest的調用
           // 在這里增加一個actXXX函數之后,即可通過objectEvent=XXX來訪問,不需要任何配置
              public Object actTest(){
            // thisObj中的變量可以在視圖中使用
            thisObj.set("testVar","hello");
            return success();
           }

           // 如果存在actBeforeAction函數,則該函數在所有action函數之前調用
           public Object actBeforeAction(){
            return success();
           }

           // 如果存在actAfterAction函數,則該函數在所有action函數之后調用
           public Object actAfterAction(){
            return success();
           }
          %>
          <%@ include file="/jsp_action_end.jsp" %>
          [/code]

          在Jsplet框架中只需要注冊對象,而不需要單獨注冊每個action。
          register.jsp
          [code]
          <%
              WebEngine.registerType("Demo", new WebActionType("/demo/action/DemoAction.jsp"),pageContext);
          %>
          [/code]

          與Jsplet 框架對比,Model2是對action的建模而不是對object的建模,即它相當于將objectName,objectEvent和 view.jsp綁定在一起定義為一個訪問點action.do,綁定過程中需要一個配置文件來固化view.jsp和action之間的聯系。因此, Model2并沒有完全分離view和model,它隱含假定著objectName只具有一個objectEvent, 并且綁定了一個具體的view(出錯頁面除外)。
          例如, 我們需要兩個不同的view來顯示同一個數據,則在Model2程序中可能需要配置兩個獨立的訪問點,而在我們的框架中只需要使用兩個不同的url:
          a_view.jsp?objectName=/@Demo&objectEvent=test
          b_view.jsp?objectName=/@Demo&objectEvent=test
          同樣的web程序甚至可以在前臺通過XMLHTTP方式來調用而不需要額外配置!

          在Jsplet框架中采用的是對象化的方式而不是Action化的方式,因此存在著多種面向對象的擴展,而所有的擴展都直接體現在url格式的細化上,一切都在陽光下。
            在Jsplet中objectName是WebObject的名稱,在全系統內唯一,其格式定義為:
          objectScope@objectType$objectInstanceId
          1. 對象類型objectType
            我們需要注冊的是對象類型而不是完整的對象名,一個對象類型可以對應于無數個完整的對象名,例如我們注冊了Demo類型的WebObject, 則
          objectName=/@DemoobjectName=/left/@Demo對應的處理文件都是DemoAction.jsp。
          2. 對象生命周期控制objectScope
            objectScope為WebObject所在的域,其格式符合Unix路徑命名規范。JSP模型本身支持一些預定義的對象域,包括page, request, session, application等。但為了能夠反映現實世界中的對象組織結構,對象域必須是允許自定義的。objectScope被組織成一個樹形結構,這是一個 基本的控制結構,其控制策略為
               同時存在的對象域之間必須存在線性序關系(order)
            當系統訪問某一對象時,如果該對象所在的對象域不能和現有對象的域處在同一"路徑"下(即當對象域之間不能建立父子關系時),系統就會自動銷毀不兼容路徑 分支下的所有對象。 這種精細的控制策略保證了系統的可擴展性,因為模型上可以保證始終只有一部分對象被創建。
          對象轉移                                                           系統動作 
          /main/@MyObject ==> /main/left/@OtherObject                       無
          /main/left/@OtherObject ==> /main/@MyObject                       無
          /main/left/@OtherObject ==> /main/left/@MyObject                  無
          /main/left/@OtherObject ==> /main/right/@MyObject                自動銷毀/main/left子域下的對象,如/main/left/@OtherObject
           
          3. 對象實例標識 objectInstanceId
           如果在某一對象域中需要包含多個同一類型的對象,可以通過objectInstanceId來加以區分,這樣在同一個頁面上我們可以使用多個同樣類型的對象。

          Jsplet中另外一個擴展是通過事件路由來支持jsp子頁面的對象化。例如
          http://my.com/demo_main.jsp?objectName=/@Main&eventTarget=/@Sub&objectEvent=test
          如果指定了eventTarget參數,則objectEvent由eventTarget對應的對象來響應。
          在jsp文件內部我們可以通過include語法來引入子對象,例如
             <jsp:include page="
          sub_view.jsp?objectName=/@Sub" />
          (注:我不是非常清楚Tapestry具體是如何實現對象化的,熟悉Tapestry的朋友可以介紹一下)

          在Jsplet中可以通過配置文件來支持對Action的interception, 例如
          [code]
          <factory>
          <listener-filter  class="global.LogFilter" />
          <post-listener class="global.CommonActions"/>

          <type name="Demo">
           <!-- 如果未指定object, 則缺省為WebObject類型 -->
           <object class="demo.MyWebObject" />
           <listener>
            <filter event="query*|select*" class="demo.LogFilter" />
            <url-listener url="/demo/DemoAction.jsp" />
            <url-listener url="/demo/DemoAction2.jsp" />
           </listener>
          </type>

          </factory>
          [/code]
          在上面這個配置文件中,DemoAction.jsp和DemoAction2.jsp是chain關系,即事件響應的傳播模型中,如果event沒有被標記為stopPropagation,就會傳遞到下一個listener。

          綜上所述,可以看到在目前多變的需求環境下,Model 2已不是一種非常完善的Web程序模式,一些重要的設計需求在Model 2模式的推方式中很難得到合適的表達。

          Feedback

          # re: [導入]jsplet:對Model 2模式的批判  回復  更多評論   

          2006-01-17 16:14 by freeboy
          Model2所有的路由(就是路徑轉向),由配置文件指定.用戶必須有一個Action頂點才能到達其他的點.所有的過程都是經過了配置文件.是典型的接收請求---->處理請求--->顯示.---------------太集中的處理請求模式

          而你這個jsplet是通過jsp頁面的轉向.然后攔截(engine.jsp).完成數據填充(也就是Action功能),因為你在URL指定了jsp路徑.不需要繼續轉向了.所以也沒有了配置文件.
          Action中的轉向配置分散到了各個URL中.然后你通過register.jsp集中對這些Action進行管理.用戶要什么顯示------>系統處理(通過Action權限驗證,填充this數據)------>返回.------------------分散處理界面模式,適度集中,減少難度.

          覺得兩種結構各有優劣,偏向于頁面轉向的這種模式比較好.可以先寫好所有的頁面轉向關系(界面流程),然后在也寫Action也不遲,適合快速原型模型.而向struts,必須寫好Action,配置轉向,繪制簡單頁面.在頁面上寫上基本流程.Action模式更適合權限控制,尤其是復雜的權限控制.

          你這個問題難以解決的問題:這個函數的返回情況是不確定的,需要由一個額外的配置文件來確定.如果確實需要這種情況呢,根據傳入的參數不同,得到不同結果.
          如:用戶通過一個下拉列表選擇輸出直方圖,表格,曲線,然后點擊一個按鈕讓產生輸出.
          覺得配合兩種更好一點,不過好像沒有這種東西:(,而且復雜度會增加.

          主站蜘蛛池模板: 温州市| 博爱县| 桂阳县| 依兰县| 光泽县| 昆明市| 裕民县| 阿勒泰市| 内丘县| 吉木乃县| 皋兰县| 聂拉木县| 兴文县| 格尔木市| 中西区| 资阳市| 临清市| 行唐县| 达州市| 静乐县| 房产| 潜山县| 岢岚县| 娄底市| 清水河县| 阳西县| 天津市| 贵溪市| 湖南省| 乌鲁木齐县| 会宁县| 木兰县| 齐齐哈尔市| 赤壁市| 阳新县| 钟山县| 襄樊市| 太和县| 二连浩特市| 通化市| 龙胜|