第四章 LPMT中的MVC多层架构实现
在
LPMT
中,为了使得系统可扩展、易维护、易修改、结构清晰,我们采用
MVC
设计模式,构建多层的体系结构,通过各层的协调配合,实现系统需求。
在
LPMT
中,我们设置了
View
、
Controller
、
Logic
、
Model
、
Data Persistence
五个逻辑层,通过各逻辑层之间的配合,应用
MVC
设计模式,实现系统需求。
4.1.1
Data Persistence
也称数据持久层。数据持久层负责数据库映射,隔离数据库操作,将数据库操作设计成
Java APIs
。此逻辑层可由
Hibernate
、
DAO
、
Connection Pool
等多种技术实现。在
LPMT
中,我们采用
Hibernate
技术,将数据库的表映射成为对象
(issuecontrol.objects
包
)
,比如
Issue
表对应
Issue.java
、
Flag
表对应
Flag.java
、
IssueData
表对应
IssueData.java
等,将对数据库的各种操作封装在
IssueDAO
和
UserDAO
两个
DAO
类中。
DAO
类代码见附录。
4.1.2
Logic
也称事务逻辑层。在一个规范的
J2EE
架构中,不同层的数据表示应该被限制在层内,而不应该扩散到其它层,这样可以降低层间的耦合性,提高
J2EE
架构整体的可维护性和可扩展性。比如说
View
层的逻辑进行了修改,那么只需要修改
ActionForm
的结构,而不需要触动
Data Persistence
层和
Logic
层的代码修改。同样,当数据库表进行了小的调整,那么也只需要修改
Data Persistence
层数据表示,而不需要触动
Model
层代码和
View
层代码。因此,我们在
Model
层和
Data Persistence
层中间插入
Logic
层,以降低
Data Persistence
和
Model
层之间的耦合关系。
Logic
层类以
Bean
结尾,如
IssueBean.java
、
UserBean.java
。
Model
通过
Logic Bean
调用
Data Persistence
层的
DAO
类,实现对数据库操作以及其他业务逻辑操作。
Bean
类代码见附录。
4.1.3
Model
也称对象层。包括所有
Action
类、
ActionForm
类、和其他显示类
(issuecontrol.actionform
包、
issuecontrol.action
包、
issuecontrol.view
包
)
。
issuecontrol.actionform
包中的所有类都派生自
ActionForm
,与
View
层的表单页面一一对应,用于定义客户端显示表单,封装业务数据,在
Logic
、
Model
、
Controller
、
View
各逻辑层之间作为数据传输媒介。在
J2EE
架构里面,
ActionForm
可以由
Entity Bean
和
Session Bean
来表示,以期实现业务逻辑重用。
Issuecontrol.view
包为显示包,其中的类为显示类,负责特殊对象表单的显示,比如分页显示的
Issue
等。
Issuecontrol.action
包中的所有类都派生自
Action
,用于封装具体的处理逻辑,调用
Logic
层的业务逻辑类,实现业务操作,读写
ActionForm
类,并将结果返回
View
层显示。部分
Action
和
ActionForm
见附录。
4.1.4
Controller
也称控制层。包括
ActionServlet
、
ActionMapping
、
RequestProcessor
等
Struts
类。
ActionServlet
负责接受用户请求,并将用户请求引导到正确的页面。
ActionMapping
包含
ActionServlet
的目标映射,
RequestProcessor
负责与
Action
交互。
ActionMapping
的目标映射在
struts-config.xml
配置文件中完成。
Struts-config.xml
代码见附录。
4.1.5
View
也称显示层。由
JSP
页面组成。每个
JSP
页面由
HTML
和
Struts
标签库实现控制和显示逻辑。部分
View
代码见附录。
上述各逻辑层各司其职,互相配合,尽量降低逻辑层之间的耦合性,提高内聚性。图
11
为上述逻辑层之间的关系。
(1)
客户端向服务器提交
Http
请求
(2)
ActionServlet
接受客户端提交的
Http
请求,载入属性文件
(Properties files)
,选择目标
Action
,将控制权交给
RequestProcessor
。
(3)
RequestProcessor
根据
URL
和
struts-config.xml
中的
actionmapping
寻找相应的
Action
;新建或者复用对应的
ActionForm
,封装包含在请求信息中的表单属性,检查数据的合法性,并将
ActionFor
传递给目标
Action
。
(4)
目标
Action
接受传递过来的
ActionForm
,读出
ActionForm
里面的属性,调用
Logic
层的业务逻辑
Bean
,而
Bean
则调用相应
DAO
类的方法,进行持久对象的持久化操作,最终完成相应的业务逻辑操作。操作过程一旦出现异常,
Action
也将一并处理。在完成业务逻辑操作后,
Action
返回一个
ActionMapping
对象,告诉
RequestProcessor
指向目标
View
页面。
(5)
View
页面利用既定接口,将结果显示给客户端。
下面以分页显示所有
Issue
为例,说明上述各逻辑层之间是如何配合以完成既定操作。
(1)
客户端向服务器提交
URL
请求:
http://localhost:8000/issuecontrol/issueAction.do
(2)
ActionServlet
通过
RequestProcessor
将请求提交到
IssueAction
(3)
Action
判断此次的请求类型为显示,参数
action = “view”
;通过
HttpServletRequest.getParameter
方法取得当前页码
viewPage
;假如
viewPage
为空,则当前页码为
1
;设定每页显示的行数
pageSize = 8
;调用
IssueBean.getIssueByPage(new Page(pageNum,pageSize))
方法,将结果封装到一个
PageView
对象
selectPageView
中;调用
httpServletRequest.setAttribute
方法将结果放到
HttpServletRequest
中;返回一个
ActionMapping
对象,内包含目标映射
viewIssue
指向
IssueList.jsp
,将控制权交还给
RequestProcessor
。
IssueBean.getIssueByPage
方法是通过调用
IssueDAO.getIssueByPage
方法完成其业务逻辑的。
(4)
RequestProcessor
将页面导向
IssueList.jsp
。
(5)
IssueList.jsp
将结果显示在客户端。
Action
中的代码块示例如下:
String viewPage=httpServletRequest.getParameter("viewPage");
int pageNum=1;
String address = "viewIssue";
//
查看所有的
Issue
if(("view".equals(action)) || (action == null)) {
address = "viewIssue";
if((viewPage!= null)&&(viewPage.length()!= 0)){
pageNum = Integer.parseInt(viewPage);
}
int pageSize=8;
//1.
先进行参数分析
//2.
下面调用逻辑层方法得到显示的对象
PageView selectPageView=IssueBean.getIssueByPage(new Page(pageNum,pageSize));
//3.
放到
request
中然后转发
httpServletRequest.setAttribute("items",selectPageView.getItems());
httpServletRequest.setAttribute("selectPageView",selectPageView);
httpServletRequest.setAttribute("action",action);
}