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