第四章 LPMT中的MVC多層架構(gòu)實(shí)現(xiàn)
在
LPMT
中,為了使得系統(tǒng)可擴(kuò)展、易維護(hù)、易修改、結(jié)構(gòu)清晰,我們采用
MVC
設(shè)計(jì)模式,構(gòu)建多層的體系結(jié)構(gòu),通過各層的協(xié)調(diào)配合,實(shí)現(xiàn)系統(tǒng)需求。
在
LPMT
中,我們?cè)O(shè)置了
View
、
Controller
、
Logic
、
Model
、
Data Persistence
五個(gè)邏輯層,通過各邏輯層之間的配合,應(yīng)用
MVC
設(shè)計(jì)模式,實(shí)現(xiàn)系統(tǒng)需求。
4.1.1
Data Persistence
也稱數(shù)據(jù)持久層。數(shù)據(jù)持久層負(fù)責(zé)數(shù)據(jù)庫(kù)映射,隔離數(shù)據(jù)庫(kù)操作,將數(shù)據(jù)庫(kù)操作設(shè)計(jì)成
Java APIs
。此邏輯層可由
Hibernate
、
DAO
、
Connection Pool
等多種技術(shù)實(shí)現(xiàn)。在
LPMT
中,我們采用
Hibernate
技術(shù),將數(shù)據(jù)庫(kù)的表映射成為對(duì)象
(issuecontrol.objects
包
)
,比如
Issue
表對(duì)應(yīng)
Issue.java
、
Flag
表對(duì)應(yīng)
Flag.java
、
IssueData
表對(duì)應(yīng)
IssueData.java
等,將對(duì)數(shù)據(jù)庫(kù)的各種操作封裝在
IssueDAO
和
UserDAO
兩個(gè)
DAO
類中。
DAO
類代碼見附錄。
4.1.2
Logic
也稱事務(wù)邏輯層。在一個(gè)規(guī)范的
J2EE
架構(gòu)中,不同層的數(shù)據(jù)表示應(yīng)該被限制在層內(nèi),而不應(yīng)該擴(kuò)散到其它層,這樣可以降低層間的耦合性,提高
J2EE
架構(gòu)整體的可維護(hù)性和可擴(kuò)展性。比如說
View
層的邏輯進(jìn)行了修改,那么只需要修改
ActionForm
的結(jié)構(gòu),而不需要觸動(dòng)
Data Persistence
層和
Logic
層的代碼修改。同樣,當(dāng)數(shù)據(jù)庫(kù)表進(jìn)行了小的調(diào)整,那么也只需要修改
Data Persistence
層數(shù)據(jù)表示,而不需要觸動(dòng)
Model
層代碼和
View
層代碼。因此,我們?cè)?/span>
Model
層和
Data Persistence
層中間插入
Logic
層,以降低
Data Persistence
和
Model
層之間的耦合關(guān)系。
Logic
層類以
Bean
結(jié)尾,如
IssueBean.java
、
UserBean.java
。
Model
通過
Logic Bean
調(diào)用
Data Persistence
層的
DAO
類,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)操作以及其他業(yè)務(wù)邏輯操作。
Bean
類代碼見附錄。
4.1.3
Model
也稱對(duì)象層。包括所有
Action
類、
ActionForm
類、和其他顯示類
(issuecontrol.actionform
包、
issuecontrol.action
包、
issuecontrol.view
包
)
。
issuecontrol.actionform
包中的所有類都派生自
ActionForm
,與
View
層的表單頁(yè)面一一對(duì)應(yīng),用于定義客戶端顯示表單,封裝業(yè)務(wù)數(shù)據(jù),在
Logic
、
Model
、
Controller
、
View
各邏輯層之間作為數(shù)據(jù)傳輸媒介。在
J2EE
架構(gòu)里面,
ActionForm
可以由
Entity Bean
和
Session Bean
來表示,以期實(shí)現(xiàn)業(yè)務(wù)邏輯重用。
Issuecontrol.view
包為顯示包,其中的類為顯示類,負(fù)責(zé)特殊對(duì)象表單的顯示,比如分頁(yè)顯示的
Issue
等。
Issuecontrol.action
包中的所有類都派生自
Action
,用于封裝具體的處理邏輯,調(diào)用
Logic
層的業(yè)務(wù)邏輯類,實(shí)現(xiàn)業(yè)務(wù)操作,讀寫
ActionForm
類,并將結(jié)果返回
View
層顯示。部分
Action
和
ActionForm
見附錄。
4.1.4
Controller
也稱控制層。包括
ActionServlet
、
ActionMapping
、
RequestProcessor
等
Struts
類。
ActionServlet
負(fù)責(zé)接受用戶請(qǐng)求,并將用戶請(qǐng)求引導(dǎo)到正確的頁(yè)面。
ActionMapping
包含
ActionServlet
的目標(biāo)映射,
RequestProcessor
負(fù)責(zé)與
Action
交互。
ActionMapping
的目標(biāo)映射在
struts-config.xml
配置文件中完成。
Struts-config.xml
代碼見附錄。
4.1.5
View
也稱顯示層。由
JSP
頁(yè)面組成。每個(gè)
JSP
頁(yè)面由
HTML
和
Struts
標(biāo)簽庫(kù)實(shí)現(xiàn)控制和顯示邏輯。部分
View
代碼見附錄。
上述各邏輯層各司其職,互相配合,盡量降低邏輯層之間的耦合性,提高內(nèi)聚性。圖
11
為上述邏輯層之間的關(guān)系。
(1)????
客戶端向服務(wù)器提交
Http
請(qǐng)求
(2)????
ActionServlet
接受客戶端提交的
Http
請(qǐng)求,載入屬性文件
(Properties files)
,選擇目標(biāo)
Action
,將控制權(quán)交給
RequestProcessor
。
(3)????
RequestProcessor
根據(jù)
URL
和
struts-config.xml
中的
actionmapping
尋找相應(yīng)的
Action
;新建或者復(fù)用對(duì)應(yīng)的
ActionForm
,封裝包含在請(qǐng)求信息中的表單屬性,檢查數(shù)據(jù)的合法性,并將
ActionFor
傳遞給目標(biāo)
Action
。
(4)????
目標(biāo)
Action
接受傳遞過來的
ActionForm
,讀出
ActionForm
里面的屬性,調(diào)用
Logic
層的業(yè)務(wù)邏輯
Bean
,而
Bean
則調(diào)用相應(yīng)
DAO
類的方法,進(jìn)行持久對(duì)象的持久化操作,最終完成相應(yīng)的業(yè)務(wù)邏輯操作。操作過程一旦出現(xiàn)異常,
Action
也將一并處理。在完成業(yè)務(wù)邏輯操作后,
Action
返回一個(gè)
ActionMapping
對(duì)象,告訴
RequestProcessor
指向目標(biāo)
View
頁(yè)面。
(5)????
View
頁(yè)面利用既定接口,將結(jié)果顯示給客戶端。
下面以分頁(yè)顯示所有
Issue
為例,說明上述各邏輯層之間是如何配合以完成既定操作。
(1)????
客戶端向服務(wù)器提交
URL
請(qǐng)求:
http://localhost:8000/issuecontrol/issueAction.do
(2)????
ActionServlet
通過
RequestProcessor
將請(qǐng)求提交到
IssueAction
(3)????
Action
判斷此次的請(qǐng)求類型為顯示,參數(shù)
action = “view”
;通過
HttpServletRequest.getParameter
方法取得當(dāng)前頁(yè)碼
viewPage
;假如
viewPage
為空,則當(dāng)前頁(yè)碼為
1
;設(shè)定每頁(yè)顯示的行數(shù)
pageSize = 8
;調(diào)用
IssueBean.getIssueByPage(new Page(pageNum,pageSize))
方法,將結(jié)果封裝到一個(gè)
PageView
對(duì)象
selectPageView
中;調(diào)用
httpServletRequest.setAttribute
方法將結(jié)果放到
HttpServletRequest
中;返回一個(gè)
ActionMapping
對(duì)象,內(nèi)包含目標(biāo)映射
viewIssue
指向
IssueList.jsp
,將控制權(quán)交還給
RequestProcessor
。
IssueBean.getIssueByPage
方法是通過調(diào)用
IssueDAO.getIssueByPage
方法完成其業(yè)務(wù)邏輯的。
(4)????
RequestProcessor
將頁(yè)面導(dǎo)向
IssueList.jsp
。
(5)????
IssueList.jsp
將結(jié)果顯示在客戶端。
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.
先進(jìn)行參數(shù)分析
????? //2.
下面調(diào)用邏輯層方法得到顯示的對(duì)象
????? PageView selectPageView=IssueBean.getIssueByPage(new Page(pageNum,pageSize));
????? //3.
放到
request
中然后轉(zhuǎn)發(fā)
????? httpServletRequest.setAttribute("items",selectPageView.getItems());
????? httpServletRequest.setAttribute("selectPageView",selectPageView);
????? httpServletRequest.setAttribute("action",action);
}