第四章 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);
}