软件复用是将已有的软件及其有效成分用于构造新的软件或系统。它不仅是对软件程序的复用,还包括对软件生产过程中其它劳动成果的复用,如项目计划书、可行性报告、需求分析、概要设计、详细设计、编码
(
源程序
)
、测试用例、文档与使用手册等等。面对越来越复杂的业务逻辑,软件复用技术一直以来都是业界关注的焦点,相关理论和技术层出不穷。作为一种比较出色的实现
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 阅读(2547)
评论(1) 编辑 收藏 所属分类:
Java 、
毕业设计文档