軟件復用是將已有的軟件及其有效成分用于構造新的軟件或系統。它不僅是對軟件程序的復用,還包括對軟件生產過程中其它勞動成果的復用,如項目計劃書、可行性報告、需求分析、概要設計、詳細設計、編碼
(
源程序
)
、測試用例、文檔與使用手冊等等。面對越來越復雜的業務邏輯,軟件復用技術一直以來都是業界關注的焦點,相關理論和技術層出不窮。作為一種比較出色的實現
MVC
設計模式的
FrameWork
,
Jakarta Struts
提供了一種比較理想的軟件復用方法。在
LPMT
中,我們對其中的代碼復用進行了有益的嘗試。
這里的
Model
包括所有的
Action
類、
ActionForm
類。
在
LPMT
中,我們設計了兩個
Action
:
IssueAction
和
MainAction
。其中,
IssueAction
負責
IssueAction
及
IssueData
、
ChangeLog
操作,
MainAction
負責
User
及
Login
操作,據此實現
Action
復用。在每個
Action
中,通過參數
action
的值來判斷操作的類型,繼而實現相應的業務邏輯操作;
IssueAction
:
//
查看所有的
Issue
?if(("view".equals(action)) || (action == null)) {
}
?//
查看單個
Issue
及其
IssueDatas
和
ChangeLogs
?else if("viewDetail".equals(action)) {
}
?//
新建一個
Issue
?else if("create".equals(action)) {
}
?//
編輯已有的
Issue
?else if("edit".equals(action)) {
}
?//
刪除對應的
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
:
??? //
判斷用戶是否取消操作
,
是則就轉向
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"))
??? {
??? }
??? //
判斷是否要刪除用戶
??? if(request.getParameter("action").equals("deleteUser"))
??? {
??? }
??? //
刪除用戶
??? if(request.getParameter("action").equals("doDeleteUser"))
??? {
??? }
??? //
查看用戶列表
??? if(request.getParameter("action").equals("viewUser"))
??? {
??? }
通過參數
address
來保留下一步的映射目標;在
struts-config.xml
配置文件中,我們通過
global-forward
和
action-forward
映射,將不同的
address
映射到相應的目標
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>
在必要的時候,
IssueAction
和
MainAction
可以合為一個
Action
,由這個
Action
來負責所有業務邏輯操作。
在面向對象設計之后,對于每個需要顯示的實體對象,我們定義了一個
ActionForm
,如
IssueActionForm
、
ComponentActionForm
、
PriorityActionForm
、
TypeActionForm
、
LogActionForm
。
ActionForm
實現了
Serializable
接口,每個
xxxActionForm
繼承
ActionForm
類,適合用于數據封裝、顯示和遠程網絡傳播。
通過在
struts-config.xml
中的映射,一個
Action
可以對應多個
ActionForm
,實現
Action
和
ActionForm
復用。
? <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>
這里的
View
主要是指用
Jakarta Struts
標簽庫構建起來的
JSP
頁面。正如本文“
LPMT
中的控制結構”和“
WebForm
的
Jakarta Struts
標簽技術實現”部分所說的,通過
<logic:equal>
標簽和
Action
、
ActionForm
中
action
、
actionType
參數的設置,可以很容易將創建、查看、修改、刪除等功能的
View
顯示集合在一個
JSP
頁面完成。理論上,可以只創建一個
View
,但是由此所帶來的創建、修改和維護成本將不合算。所以我們通常把相同或相似的業務邏輯結果顯示放在一個
View
中完成,以此實現
View
的復用。
Struts
的
Controller
由
ActionServlet
、
RequestProcessor
、
ActionMapping
等類組成。這些類在
Struts
中唯一充當控制器角色,
Model
中相應的
ActionForm
和
URL
中的參數則作為數據封裝和傳遞的媒介。這些類通過相應的方法和接口復用,實現
Model
的復用。
在
LPMT
中,我們采用了面向對象的分析、設計和編碼方法,因此,我們主要著眼于面向對象思想在下面幾個方面實現代碼復用:
7.4.1
封裝性
在軟構件的定義中,用戶只關心事件的輸入輸出,對事件內部不必關心,方法和事件是獨立于應用的,用戶可以在軟構件中定義自己的事件,對于內部的復雜性調用這并不知曉,從而提高了隱蔽性。在
Logic
、
DataPersistence
等相關
Bean
和
DAO
類中,我們遵循數據封裝和持久原則,在
Action
中調用相關方法只要符合相應的輸入和輸出條件即可實現既定的業務邏輯操作
,
而不需要了解業務邏輯的處理過程。
7.4.2
重載
重載就是在同一軟件構件中用同一名字來表示不同的方法名。一般有兩種實現方法,一是方法參數的個數重載,二是方法參數的類型重載。在
IssueDAO
中,根據應用需求,我們定義了
delOneLog
方法,通過方法參數的類型(
Log
類型、
Long
類型)不同實現重載。另外的
getIssueByPage
方法,則通過方法參數的個數不同實現重載。詳細代碼參考附錄。
7.4.3
繼承
繼承就是高層的類在不同范圍的復用。在
Web
系統設計中,經常需要驗證客戶端的輸入是否符合要求,比如輸入不能為空、
Email
段輸入必須符合規范等等。在
Model
層的
ActionForm
類中,我們定義了一個高層類
BaseForm
,
BaseForm
擴展了
ActionForm
,定義了幾個常用的數據驗證方法,比如驗證輸入是否為空的
isBlankString
方法、驗證前后輸入是否一樣的
isTheSame
等。其他的
ActionForm
通過繼承
BaseForm
實現。另外一種方法,可以通過定義一個
ValidateForm
的靜態類來負責常用的幾種輸入驗證,其他
ActionForm
類在
Validate
方法中通過調用
ValidateForm
類的相應方法即可實現相應的輸入驗證邏輯。
結論
通過上述背景闡述、技術分析和代碼實踐,可以看到,使用
Struts
構建的實現了
MVC
設計模式的系統,在提高系統的構建效率、可擴展性、可維護性、可復用性方面均有突出的表現。而本文在
LPMT
中的
Struts
應用方式比如架構設計、
WebForm
構建技術等有效的發揮了
Struts
技術的優勢,快速實現了系統的應用需求,有一定的參考價值。
致謝語
在本文寫作和系統設計過程中,林勁松老師給了大量熱心的幫助和指導,在此特別感謝。作者的同組同學范曉鑫和羅佳在系統設計和編碼方面也讓作者受益頗多,作者在廈門合強軟件有限公司的同事在
MVC
思想方面給了作者很大的提示和幫助,在此一并感謝。同時要感謝自動化系所有的老師和同學在大學四年對作者的關心和幫助。
參考文獻
(1)
???
James Goodwill《Mastering Jakarta Struts》Indianapolis, Indiana,Canada Wiley Publishing ,Inc.2002年
(2)
???
Hafech Mili,Ali Mili,Sherif Yacoub etal著,韓柯譯《基于重用的軟件工程》北京電子工業出版社 2003年
(3)
???
孫琪《軟件復用技術概述》http://www.tongtech.com/jsqy/yqxwview.asp?id=209? 2003年6月30日
(4)
???
趙晨希
《用Struts建立MVC應用的介紹》
http://www-900.ibm.com/developerWorks/cn/java/l-struts-mvc/index.shtml
?2002
年 12 月
(5)
???
劉天北 《理解企業應用框架》http://www.socent.com/crm_oa/message.asp?id=1182003年7月1日
21MM
《框架不是框框
—
應用框架的基本思想》
http://www.digitalspirit.info/phf/artichecture/applyFrame.htm
posted on 2005-01-27 14:53
eamoi 閱讀(2556)
評論(1) 編輯 收藏 所屬分類:
Java 、
畢業設計文檔