隨筆-86  評(píng)論-767  文章-3  trackbacks-3

          第七章 LPMT中的代碼復(fù)用技術(shù)

          軟件復(fù)用是將已有的軟件及其有效成分用于構(gòu)造新的軟件或系統(tǒng)。它不僅是對(duì)軟件程序的復(fù)用,還包括對(duì)軟件生產(chǎn)過程中其它勞動(dòng)成果的復(fù)用,如項(xiàng)目計(jì)劃書、可行性報(bào)告、需求分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼 ( 源程序 ) 、測(cè)試用例、文檔與使用手冊(cè)等等。面對(duì)越來越復(fù)雜的業(yè)務(wù)邏輯,軟件復(fù)用技術(shù)一直以來都是業(yè)界關(guān)注的焦點(diǎn),相關(guān)理論和技術(shù)層出不窮。作為一種比較出色的實(shí)現(xiàn) MVC 設(shè)計(jì)模式的 FrameWork Jakarta Struts 提供了一種比較理想的軟件復(fù)用方法。在 LPMT 中,我們對(duì)其中的代碼復(fù)用進(jìn)行了有益的嘗試。

          7.1 Model復(fù)用

          這里的 Model 包括所有的 Action 類、 ActionForm 類。

          LPMT 中,我們?cè)O(shè)計(jì)了兩個(gè) Action IssueAction MainAction 。其中, IssueAction 負(fù)責(zé) IssueAction IssueData ChangeLog 操作, MainAction 負(fù)責(zé) User Login 操作,據(jù)此實(shí)現(xiàn) Action 復(fù)用。在每個(gè) Action 中,通過參數(shù) action 的值來判斷操作的類型,繼而實(shí)現(xiàn)相應(yīng)的業(yè)務(wù)邏輯操作;

          IssueAction

          // 查看所有的 Issue

          ?if(("view".equals(action)) || (action == null)) {

          }

          ?// 查看單個(gè) Issue 及其 IssueDatas ChangeLogs

          ?else if("viewDetail".equals(action)) {

          }

          ?// 新建一個(gè) Issue

          ?else if("create".equals(action)) {

          }

          ?// 編輯已有的 Issue

          ?else if("edit".equals(action)) {

          }

          ?// 刪除對(duì)應(yīng)的 Issue

          ?else if("delete".equals(action)) {

          }

          ?// 保存新建的 Issue

          ?else if("save".equals(action)) {

          }

          ?// 新建 IssueData

          ?else if("createIssueData".equals(action)) {

          }

          ?// 保存新建的 IssueData

          ?else if("saveIssueData".equals(action)) {

          }

          ?// 編輯 IssueData

          ?else if("editIssueData".equals(action)) {

          }

          ?// 刪除 IssueData

          ?else if("deleteIssueData".equals(action)) {

          }

          MainAction

          ??? // 判斷用戶是否取消操作 , 是則就轉(zhuǎn)向 main.jsp

          ??? if(this.isCancelled(request))

          ??? {

          ??? }

          ??? // 登陸

          ??? if(request.getParameter("action").equals("login"))

          ??? {

          ??? }

          ??? // 顯示添加新用戶界面

          ??? if(request.getParameter("action").equals("newUser"))

          ??? {

          ??? }

          ??? // 添加新用戶

          ?? ?if(request.getParameter("action").equals("doNewUser"))

          ??? {

          ??? }

          ??? // 顯示要修改的用戶的資料

          ??? if(request.getParameter("action").equals("updateUser"))

          ??? {

          ??? }

          ??? // 修改用戶資料

          ??? if(request.getParameter("action").equals("doUpdateUser"))

          ??? {

          ??? }

          ??? // 判斷是否要?jiǎng)h除用戶

          ??? if(request.getParameter("action").equals("deleteUser"))

          ??? {

          ??? }

          ??? // 刪除用戶

          ??? if(request.getParameter("action").equals("doDeleteUser"))

          ??? {

          ??? }

          ??? // 查看用戶列表

          ??? if(request.getParameter("action").equals("viewUser"))

          ??? {

          ??? }

          通過參數(shù) address 來保留下一步的映射目標(biāo);在 struts-config.xml 配置文件中,我們通過 global-forward action-forward 映射,將不同的 address 映射到相應(yīng)的目標(biāo) View

          ? ?? <global-forwards>

          ??? ????? <forward name="loginSuccess" path="/main.jsp" />

          ??? ????? <forward name="newUser" path="/newUser.jsp"/>

          ??? ????? <forward name="updateUser" path="/newUser.jsp"/>

          ??? ????? <forward name="deleteUser" path="/deleteUser.jsp"/>

          ??? ????? <forward name="login" path="/index.jsp"/>

          ??? ????? <forward name="success" path="/message.jsp"/>

          ?????? ?????? <forward name="operationSuccess" path="/Success.jsp" />

          ??? ????? <forward name="error" path="/error.jsp"/>

          ??? ????? <forward name="viewUser" path="/viewUser.jsp"/>

          ? ?? </global-forwards>

          ??? <action name="issueActionForm" type="issuecontrol.action.IssueAction" validate="false" scope="request" path="/issueAction">

          ????? ? <forward name="viewIssue" path="/IssueList.jsp" />

          ????? ? <forward name="viewIssueDetail" path="/IssueDetail.jsp" />

          ????? ? <forward name="issueData" path="/IssueData.jsp" />

          </action>

          在必要的時(shí)候, IssueAction MainAction 可以合為一個(gè) Action ,由這個(gè) Action 來負(fù)責(zé)所有業(yè)務(wù)邏輯操作。

          在面向?qū)ο笤O(shè)計(jì)之后,對(duì)于每個(gè)需要顯示的實(shí)體對(duì)象,我們定義了一個(gè) ActionForm ,如 IssueActionForm ComponentActionForm PriorityActionForm TypeActionForm LogActionForm ActionForm 實(shí)現(xiàn)了 Serializable 接口,每個(gè) xxxActionForm 繼承 ActionForm 類,適合用于數(shù)據(jù)封裝、顯示和遠(yuǎn)程網(wǎng)絡(luò)傳播。

          通過在 struts-config.xml 中的映射,一個(gè) Action 可以對(duì)應(yīng)多個(gè) ActionForm ,實(shí)現(xiàn) Action ActionForm 復(fù)用。

          ? <form-beans>

          ??? <form-bean name="LoginForm" type="issuecontrol.actionform.LoginForm" />

          ??? <form-bean name="NewUserForm" type="issuecontrol.actionform.NewUserForm"/>

          ??? <form-bean name="BaseForm" type="issuecontrol.actionform.BaseForm"/>

          ?????? <form-bean name="loginActionForm" type="issuecontrol.actionform.LoginActionForm" />

          ??? <form-bean name="componentActionForm" type="issuecontrol.actionform.ComponentActionForm" />

          ??? <form-bean name="environmentActionForm" type="issuecontrol.actionform.EnvironmentActionForm" />

          ??? <form-bean name="flagActionForm" type="issuecontrol.actionform.FlagActionForm" />

          ??? <form-bean name="issueActionForm" type="issuecontrol.actionform.IssueActionForm" />

          ??? <form-bean name="logActionForm" type="issuecontrol.actionform.LogActionForm" />

          ??? <form-bean name="priorityActionForm" type="issuecontrol.actionform.PriorityActionForm" />

          ??? <form-bean name="typeActionForm" type="issuecontrol.actionform.TypeActionForm" />

          ??? <form-bean name="issueDataActionForm" type="issuecontrol.actionform.IssueDataActionForm"/>

          ? </form-beans>

          ? <action-mappings>

          ??? <action name="LoginForm" type="issuecontrol.action.MainAction" validate="true" scope="session" input="/index.jsp" path="/login" />

          ??? <action path="/newUser" name="BaseForm" type="issuecontrol.action.MainAction" validate="false" scope="request" input="/main.jsp"/>

          ??? <action path="/doNewUser" name="NewUserForm" type="issuecontrol.action.MainAction" validate="true" scope="request" input="/newUser.jsp"/>

          ??? <action path="/viewUser" name="BaseForm" type="issuecontrol.action.MainAction" validate="false" scope="request" input="/main.jsp"/>

          ??? <action path="/updateUser" name="BaseForm" type="issuecontrol.action.MainAction" validate="false" scope="request" input="/viewUser.jsp"/>

          ??? <action path="/doUpdateUser" name="NewUserForm" type="issuecontrol.action.MainAction" validate="true" scope="request" input="/newUser.jsp"/>

          ??? <action path="/deleteUser" name="BaseForm" type="issuecontrol.action.MainAction" validate="false" scope="request" input="/viewUser.jsp"/>

          ??? <action path="/doDeleteUser" name="BaseForm" type="issuecontrol.action.MainAction" validate="false" scope="request" input="/deleteUser.jsp"/>

          ??? <action name="issueActionForm" type="issuecontrol.action.IssueAction" validate="false" scope="request" path="/issueAction">

          ??? </action>

          ?????? <action name="issueDataActionForm" type="issuecontrol.action.IssueAction" validate="false" scope="request" path="/issueDataAction"/>

          ? </action-mappings>

          7.2 View復(fù)用

          這里的 View 主要是指用 Jakarta Struts 標(biāo)簽庫構(gòu)建起來的 JSP 頁面。正如本文“ LPMT 中的控制結(jié)構(gòu)”和“ WebForm Jakarta Struts 標(biāo)簽技術(shù)實(shí)現(xiàn)”部分所說的,通過 <logic:equal> 標(biāo)簽和 Action ActionForm action actionType 參數(shù)的設(shè)置,可以很容易將創(chuàng)建、查看、修改、刪除等功能的 View 顯示集合在一個(gè) JSP 頁面完成。理論上,可以只創(chuàng)建一個(gè) View ,但是由此所帶來的創(chuàng)建、修改和維護(hù)成本將不合算。所以我們通常把相同或相似的業(yè)務(wù)邏輯結(jié)果顯示放在一個(gè) View 中完成,以此實(shí)現(xiàn) View 的復(fù)用。

          7.3 Controller復(fù)用

          Struts Controller ActionServlet RequestProcessor ActionMapping 等類組成。這些類在 Struts 中唯一充當(dāng)控制器角色, Model 中相應(yīng)的 ActionForm URL 中的參數(shù)則作為數(shù)據(jù)封裝和傳遞的媒介。這些類通過相應(yīng)的方法和接口復(fù)用,實(shí)現(xiàn) Model 的復(fù)用。

          7.4 其他面向?qū)ο蟮拇a復(fù)用

          LPMT 中,我們采用了面向?qū)ο蟮姆治觥⒃O(shè)計(jì)和編碼方法,因此,我們主要著眼于面向?qū)ο笏枷朐谙旅鎺讉€(gè)方面實(shí)現(xiàn)代碼復(fù)用:

          7.4.1 封裝性

          在軟構(gòu)件的定義中,用戶只關(guān)心事件的輸入輸出,對(duì)事件內(nèi)部不必關(guān)心,方法和事件是獨(dú)立于應(yīng)用的,用戶可以在軟構(gòu)件中定義自己的事件,對(duì)于內(nèi)部的復(fù)雜性調(diào)用這并不知曉,從而提高了隱蔽性。在 Logic DataPersistence 等相關(guān) Bean DAO 類中,我們遵循數(shù)據(jù)封裝和持久原則,在 Action 中調(diào)用相關(guān)方法只要符合相應(yīng)的輸入和輸出條件即可實(shí)現(xiàn)既定的業(yè)務(wù)邏輯操作 , 而不需要了解業(yè)務(wù)邏輯的處理過程。

          7.4.2 重載

          重載就是在同一軟件構(gòu)件中用同一名字來表示不同的方法名。一般有兩種實(shí)現(xiàn)方法,一是方法參數(shù)的個(gè)數(shù)重載,二是方法參數(shù)的類型重載。在 IssueDAO 中,根據(jù)應(yīng)用需求,我們定義了 delOneLog 方法,通過方法參數(shù)的類型( Log 類型、 Long 類型)不同實(shí)現(xiàn)重載。另外的 getIssueByPage 方法,則通過方法參數(shù)的個(gè)數(shù)不同實(shí)現(xiàn)重載。詳細(xì)代碼參考附錄。

          7.4.3 繼承

          繼承就是高層的類在不同范圍的復(fù)用。在 Web 系統(tǒng)設(shè)計(jì)中,經(jīng)常需要驗(yàn)證客戶端的輸入是否符合要求,比如輸入不能為空、 Email 段輸入必須符合規(guī)范等等。在 Model 層的 ActionForm 類中,我們定義了一個(gè)高層類 BaseForm BaseForm 擴(kuò)展了 ActionForm ,定義了幾個(gè)常用的數(shù)據(jù)驗(yàn)證方法,比如驗(yàn)證輸入是否為空的 isBlankString 方法、驗(yàn)證前后輸入是否一樣的 isTheSame 等。其他的 ActionForm 通過繼承 BaseForm 實(shí)現(xiàn)。另外一種方法,可以通過定義一個(gè) ValidateForm 的靜態(tài)類來負(fù)責(zé)常用的幾種輸入驗(yàn)證,其他 ActionForm 類在 Validate 方法中通過調(diào)用 ValidateForm 類的相應(yīng)方法即可實(shí)現(xiàn)相應(yīng)的輸入驗(yàn)證邏輯。

          結(jié)論

          通過上述背景闡述、技術(shù)分析和代碼實(shí)踐,可以看到,使用 Struts 構(gòu)建的實(shí)現(xiàn)了 MVC 設(shè)計(jì)模式的系統(tǒng),在提高系統(tǒng)的構(gòu)建效率、可擴(kuò)展性、可維護(hù)性、可復(fù)用性方面均有突出的表現(xiàn)。而本文在 LPMT 中的 Struts 應(yīng)用方式比如架構(gòu)設(shè)計(jì)、 WebForm 構(gòu)建技術(shù)等有效的發(fā)揮了 Struts 技術(shù)的優(yōu)勢(shì),快速實(shí)現(xiàn)了系統(tǒng)的應(yīng)用需求,有一定的參考價(jià)值。

          致謝語

          在本文寫作和系統(tǒng)設(shè)計(jì)過程中,林勁松老師給了大量熱心的幫助和指導(dǎo),在此特別感謝。作者的同組同學(xué)范曉鑫和羅佳在系統(tǒng)設(shè)計(jì)和編碼方面也讓作者受益頗多,作者在廈門合強(qiáng)軟件有限公司的同事在 MVC 思想方面給了作者很大的提示和幫助,在此一并感謝。同時(shí)要感謝自動(dòng)化系所有的老師和同學(xué)在大學(xué)四年對(duì)作者的關(guān)心和幫助。


          參考文獻(xiàn)

          (1) ??? James GoodwillMastering Jakarta StrutsIndianapolis, Indiana,Canada Wiley Publishing ,Inc.2002

          (2) ??? Hafech Mili,Ali Mili,Sherif Yacoub etal著,韓柯譯《基于重用的軟件工程》北京電子工業(yè)出版社 2003

          (3) ??? 孫琪《軟件復(fù)用技術(shù)概述》http://www.tongtech.com/jsqy/yqxwview.asp?id=209? 2003年6月30

          (4) ??? 趙晨希 《用Struts建立MVC應(yīng)用的介紹》 http://www-900.ibm.com/developerWorks/cn/java/l-struts-mvc/index.shtml ?2002 12

          (5) ??? 劉天北 《理解企業(yè)應(yīng)用框架》http://www.socent.com/crm_oa/message.asp?id=1182003年7月1

          21MM 《框架不是框框 應(yīng)用框架的基本思想》 http://www.digitalspirit.info/phf/artichecture/applyFrame.htm
          posted on 2005-01-27 14:53 eamoi 閱讀(2560) 評(píng)論(1)  編輯  收藏 所屬分類: Java畢業(yè)設(shè)計(jì)文檔

          評(píng)論:
          # re: MVC設(shè)計(jì)模式的Struts技術(shù)實(shí)現(xiàn)(4) 2005-12-04 19:47 | raymond
          太棒了  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 慈利县| 利辛县| 阿克| 丰原市| 龙里县| 柳州市| 健康| 鄂尔多斯市| 波密县| 青铜峡市| 宜都市| 皮山县| 翼城县| 扎赉特旗| 平山县| 普兰店市| 昌乐县| 金川县| 绥阳县| 阳原县| 彰化县| 施秉县| 苗栗县| 资源县| 宜春市| 清水河县| 康保县| 田林县| 通化市| 洛隆县| 龙海市| 额敏县| 大英县| 南丹县| 方正县| 安阳县| 聂拉木县| 上杭县| 海丰县| 九龙县| 台中县|