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

             在Jsp Model 2模型中, 用戶的所有請(qǐng)求提交給Controller Servlet, 由Controller進(jìn)行統(tǒng)一分配, 并且采用推的方式將不同的UI顯示給用戶。 這種推方式在很多人看來(lái)是一種優(yōu)點(diǎn),因?yàn)樵赟truts等MVC實(shí)現(xiàn)中具體推送的UI可以在配置文件中配置,配置完成后還可以通過(guò)一些可視化分析工具得到 整個(gè)站點(diǎn)地圖。在Model2模式中基本的訪問(wèn)格式為:
                 action.do?其他參數(shù)  

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

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

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

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

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

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

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

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

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

          在Jsplet中可以通過(guò)配置文件來(lái)支持對(duì)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]
          在上面這個(gè)配置文件中,DemoAction.jsp和DemoAction2.jsp是chain關(guān)系,即事件響應(yīng)的傳播模型中,如果event沒(méi)有被標(biāo)記為stopPropagation,就會(huì)傳遞到下一個(gè)listener。

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

          Feedback

          # re: [導(dǎo)入]jsplet:對(duì)Model 2模式的批判  回復(fù)  更多評(píng)論   

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

          而你這個(gè)jsplet是通過(guò)jsp頁(yè)面的轉(zhuǎn)向.然后攔截(engine.jsp).完成數(shù)據(jù)填充(也就是Action功能),因?yàn)槟阍赨RL指定了jsp路徑.不需要繼續(xù)轉(zhuǎn)向了.所以也沒(méi)有了配置文件.
          Action中的轉(zhuǎn)向配置分散到了各個(gè)URL中.然后你通過(guò)register.jsp集中對(duì)這些Action進(jìn)行管理.用戶要什么顯示------>系統(tǒng)處理(通過(guò)Action權(quán)限驗(yàn)證,填充this數(shù)據(jù))------>返回.------------------分散處理界面模式,適度集中,減少難度.

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

          你這個(gè)問(wèn)題難以解決的問(wèn)題:這個(gè)函數(shù)的返回情況是不確定的,需要由一個(gè)額外的配置文件來(lái)確定.如果確實(shí)需要這種情況呢,根據(jù)傳入的參數(shù)不同,得到不同結(jié)果.
          如:用戶通過(guò)一個(gè)下拉列表選擇輸出直方圖,表格,曲線,然后點(diǎn)擊一個(gè)按鈕讓產(chǎn)生輸出.
          覺(jué)得配合兩種更好一點(diǎn),不過(guò)好像沒(méi)有這種東西:(,而且復(fù)雜度會(huì)增加.

          主站蜘蛛池模板: 云浮市| 辽阳县| 海阳市| 安龙县| 望都县| 衡阳县| 太和县| 车险| 金沙县| 南城县| 涿州市| 襄垣县| 溧阳市| 霞浦县| 德保县| 咸宁市| 汉寿县| 玉环县| 永川市| 内丘县| 比如县| 甘泉县| 庆阳市| 宜兰市| 苍南县| 内丘县| 芦山县| 封丘县| 芦溪县| 托克逊县| 惠东县| 鄂托克旗| 新营市| 乐业县| 礼泉县| 馆陶县| 上饶市| 望城县| 温宿县| 乐陵市| 遂平县|