在
Struts
的控制邏輯中,
Controller
的
ActionServlet
、
RequestProcessor
是由
Struts
自身實現的。用戶需要實現的是
Model
的
Action
的
Perform
或者
Execute
方法。我們定義了兩個
Action
:
IssueAction
和
MainAction
,在
Action
中根據參數
action
的類型判斷并實現各種邏輯操作。下面以
IssueAction
、
IssueActionForm
、
IssueDetail.jsp
為例說明
LPMT
中的控制結構實現。
在
IssueAction
中,定義參數
action
來判斷各種操作類型。
Action
值來自客戶端請求的
URL
,
action = httpServletRequest.getParameter("action").trim()
。
action == “view”
:分頁查看所有
Issue
action == “viewDetail”
:
查看單個
Issue
及其
IssueDatas
和
ChangeLogs
action == “create”
:
新建一個
Issue
action == “edit”
:編輯選定
Issue
action == “delete”
:刪除選定
Issue
action == “save”
:保存新建或修改過的
Issue
action == ” createIssueData”
:為選定的
Issue
新建
IssueData
action == “saveIssueData”
:保存新建或修改過的
IssueData
action == “editIssueData”
:修改選定的
IssueData
action == “deleteIssueData”
:刪除選定的
IssueData
在判定操作類型之后,
Action
根據需要初始化對象,調用
IssueBean
的方法完成相應的業務邏輯操作,最后返回相應的
ActionMapping
對象。
在
IssueActionForm
中,處理對應表單頁面的所有項之外,我們另外定義了一個
actionType
參數,來保存并傳遞
Action
的操作類型。
private String actionType = "create";
在
Action
判定操作類型之后,要設置對應
IssueActionForm
對象的
actionType
值。比如:
issueActionForm.setActionType(action);
issueDataActionForm.setActionType(action);
在
IssueAction
對應的
IssueDetail.jsp
頁面中,需要根據當前
IssueActionForm
參數
actionType
的值來判斷當前操作類型,繼而實現相應的顯示邏輯。比如:
當
actionType = “create”
時,操作類型為新建
Issue
,此時顯示一張空白表單,初始化
Component
、
Environment
等可選項;當
actionType = “edit”
時,操作類型為編輯
Issue
,此時要載入表單值,如
issueId
,
title
,
Component
等等;當
actionType = “viewDetail”
時,操作類型為查看
Issue
內容。這里使用
<logic:equal>
標簽來實現控制顯示邏輯,用
<logic:present>
和
<logic:notPresent>
判斷對應的
issueActionForm
是否已經載入頁面。我們以顯示
IssueId
為例:
?????? <logic:equal name="issueActionForm" property="actionType" value="create">
????????????? <html:text property="issueId"/>
?????? </logic:equal>
?????? <logic:equal name="issueActionForm" property="actionType" value="edit">
????????????? <logic:present name="issueActionForm">
???????????????????? <html:text name="issueActionForm" property="issueId"/>
????????????? </logic:present>
????????????? <logic:notPresent name="issueActionForm">
?????????????
?????? <b>Error:No issue.</b>
????????????? </logic:notPresent>
?????? </logic:equal>
?????? <logic:equal name="issueActionForm" property="actionType" value="viewDetail">
????????????? <logic:present name="issueActionForm">
???????????????????? <bean:write name="issueActionForm" property="issueId" />
????????????? </logic:present>
????????????? <logic:notPresent name="issueActionForm">
???????????????????? <b>Error:No issue.</b>
????????????? </logic:notPresent>
?????? </logic:equal>
頁面效果如下:
在
Web
系統設計中,
WebForm
作為直接呈現給客戶端的
View
,其實現技術一直為業界所關注。從最初的單純的
HTML
,到后來的
CGI
、
PERL
,到最近的
ASP
、
JSP
,到目前的標簽庫,業界一直在尋找一種能夠快速開發、靈活、高效率、可重用的技術來實現業務邏輯呈現。在
LPMT
中,我們采用
HTML
結合
Jakarta Struts
標簽的技術來實現,
JSP
頁面作為單純的
View
使用,而業務邏輯完全由
Action
完成。同樣是運行于
Server
端的技術,與單純的
ASP
、
JSP
技術相比,運用
Jakarta Struts
標簽庫構建的
JSP
頁面結構更清晰,可重用性和擴展性更優秀。
Jakarta Struts1.0
的標簽庫包括:
l???????
Bean
標簽:
提供一組操作標簽,用于在必要的時候封裝邏輯,使用JavaBeans、HTTP Cookies、HTTP Headers。這些標簽封裝在文件名為struts-bean.tld的標簽包中。
l???????
Logical
標簽:
提供一組用來在JSP頁中有條件地產生輸出文本,在對象集合中循環從而重復地產生輸出文本,以及應用程序流程控制的標簽。Logical標簽庫定義的標記能夠執行條件邏輯、重復循環、轉發/重定向等功能,可以完全替代scriptlet。這些標簽封裝在文件名為struts-logic.tld的標簽包中。
l???????
HTML
標簽:
用來生成HTML標簽,顯示表單元素、控件及其數據,使用會話ID對URL進行編程,以及顯示錯誤信息。這些標簽封裝在文件名為struts-html.tld的標簽包中。
l???????
Templete
標簽:
提供一組用于定義可重用的模板視圖的標簽,包括:<template:get/>、<template:insert/>、<template:put>。這些標簽被封裝在文件名為struts-template.tld的標簽包中。
Struts1.1
還引入了struts-nested和struts-tiles兩個標簽庫。在LPMT中,我們采用了Struts1.0的四個標簽庫。
WebForm
即是通常
MVC
設計模式中的
View
。在
LPMT
中,
View
由通過
HTML
和
Struts
標簽構建的
JSP
頁面充當。
JSP
頁面作為
View
使用,只負責顯示業務邏輯的處理結果,并不負責業務邏輯處理。為使
View
具有較高的可復用性,通常將多個邏輯顯示集合在一個
View
完成;為使
View
具有較高的穩定性,
JSP
頁面應該保留通用的接口,即使
Action
的業務邏輯改變了,
View
仍然不需要修改。另外,為使
View
具有較高的可擴展性和可維護性,降低未來可能的維護成本,
View
結構應該清晰易讀。以
IssueDetail.jsp
為例說明
WebForm
的
Jakarta Struts
技術實現。
IssueDetail.jsp
的設計需求是要實現
Issue
創建、查看、修改、刪除的頁面顯示。當操作類型為創建
—
“
create
”時,
View
應該初始化一張空白的
Issue
表單,等待用戶輸入;當操作類型為查看
—
“
viewDetail
”時,
View
應該把相應的
Issue
的值及其
IssueData
、
ChangeLog
顯示出來,內容為不可編輯;當操作類型為修改時,
View
表單應該初始化相應
Issue
的值并于相應的
HTML
控件集合,內容為可編輯;當操作類型為刪除
—
“
delete
”時,
View
不顯示或者顯示
Issue
的內容,不可編輯。
為實現上述上述邏輯,我們采用
<logic:equal>
標簽,通過判斷
issueActionForm
對象的
actionType
參數的
value
值來判斷操作類型,繼而實現相應的顯示邏輯。以顯示
Issue
的
description
值為例,代碼實現如下:
<logic:equal name="issueActionForm" property="actionType" value="create">
????????????? <html:textarea property="description" rows="8" cols="40"/>
?????? </logic:equal>
??? <logic:equal name="issueActionForm" property="actionType" value="edit">
????????????? <logic:present name="issueActionForm">
???????????????????? <html:textarea property="description" rows="8" cols="40"/>
????????????? </logic:present>
??????
?????? <logic:notPresent name="issueActionForm">
?????????????
?????? <b>Error:No issue.</b>
??????
?????? </logic:notPresent>
?????? </logic:equal>
?????? <logic:equal name="issueActionForm" property="actionType" value="viewDetail">
????????????? <logic:present name="issueActionForm">
???????????????????? <bean:write name="issueActionForm" property="description" />
????????????? </logic:present>
????????????? <logic:notPresent name="issueActionForm">
???????????????????? <b>Error:No issue.</b>
????????????? </logic:notPresent>
?????? </logic:equal>
??????
而在
View
通用性設計方面,
IssueDetail.jsp
通過使用
<logic:present>
和
<logic:notPresent>
標簽判斷對象
issueActionForm
是否已經加載到
scope
以及加載進來的
issueActionForm
的
actionType
等屬性值來完成邏輯顯示。這意味著當
Action
完成相應的業務邏輯之后,在返回指向
IssueDetail.jsp
的
ActionMapping
對象之前,只需要把相應的
IssueActionForm
對象實例加載到如
Request
、
Session
或者
PageContext
即任何一個
scope
里面就可以了,不需要在
URL
中傳遞任何參數。
比如在
IssueAction
中,當操作類型為查看相應
Issue
的詳細內容時,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=viewDetail&issueId=...
,
IssueAction
先取得
URL
傳遞過來的
issueId
參數值,然后通過
IssueBean.getIssueById
方法取得對應的
IssueActionForm
對象實例
issueActionForm
,設置
issueActionForm
對象的
actionType
參數,把
issueActionForm
放到
httpServletRequest
對象中,最后設置轉向參數
address
的值為
”viewIssueDetail”
。代碼示例如下:
if("viewDetail".equals(action)) {
String issueId = "";
?
????????? if(httpServletRequest.getParameter("issueId")!=null)
issueId = httpServletRequest.getParameter("issueId").trim();
IssueActionForm issueActionForm = IssueBean.getIssueById(issueId);
if(issueActionForm == null) {
runningErrors.add(new ActionError("Issue(IssueID=" + issueId + ") not found."));
???????
???? httpServletRequest.setAttribute("runningErrors",runningErrors);
???????
???? address = "error";
?????
? }
?????
? else {
???????
???? httpServletRequest.setAttribute("issueActionForm",issueActionForm);
??????
????????????? issueActionForm.setActionType(action);
??????? address = "viewIssueDetail";
???
????? }
}
當操作類型為新建一個
Issue
實例的時候,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=create
,
IssueAction
取得
typeActionForm
對象數組、
componentActionForm
對象數組、
flagActionForm
對象數組、
environmentActionForm
對象數組和
priorityActionForm
對象數組并放到
httpServletRequest
對象中,最后設置轉向參數
address
的值為
”viewIssueDetail”
。代碼示例如下:
?????? else if("create".equals(action)) {
???
????? httpServletRequest.setAttribute("typeActionForms",IssueBean.getAllTypes());
httpServletRequest.setAttribute("componentActionForms",IssueBean.getAllComponents());
httpServletRequest.setAttribute("flagActionForms",IssueBean.getAllFlags());??? httpServletRequest.setAttribute("environmentActionForms",IssueBean.getAllEnvironments());
?????
? httpServletRequest.setAttribute("priorityActionForms",IssueBean.getAllPriorities());
????????????? address = "viewIssueDetail";
}
當操作類型為編輯修改一個
Issue
實例的時候,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=edit&issueId
=...
,
IssueAction
根據取得的參數
issueId
的值取得相應的
IssueActionForm
對象實例
issueActionForm
,設置
issueActionForm
的參數
actionType
的值,取得
typeActionForm
對象數組、
componentActionForm
對象數組、
flagActionForm
對象數組、
environmentActionForm
對象數組和
priorityActionForm
對象數組并將所有對象實例放到
httpServletRequest
對象中,最后設置轉向參數
address
的值為
”viewIssueDetail”
。代碼示例如下:
else if("edit".equals(action)) {
address = "viewIssueDetail";
String issueId = "";
if(httpServletRequest.getParameter("issueId") != null)
IssueId = httpServletRequest.getParameter("issueId").trim();
IssueActionForm issueActionForm = IssueBean.getIssueById(issueId);
if(issueActionForm == null) {
runningErrors.add(new ActionError("Issue(IssueID=" + issueId + ") not found."));
???
????? httpServletRequest.setAttribute("runningErrors",runningErrors);
???
????? address = "error" ;
}
else {
issueActionForm.setActionType(action);
???
????? httpServletRequest.setAttribute("issueActionForm",issueActionForm);
httpServletRequest.setAttribute("typeActionForms",IssueBean.getAllTypes());??????? httpServletRequest.setAttribute("componentActionForms",IssueBean.getAllComponents());
httpServletRequest.setAttribute("flagActionForms",IssueBean.getAllFlags());??????? httpServletRequest.setAttribute("environmentActionForms",IssueBean.getAllEnvironments());??????? httpServletRequest.setAttribute("priorityActionForms",IssueBean.getAllPriorities());
address = "viewIssueDetail";
?
???? }
}
另外,由于
View
只負責邏輯顯示,而不需要實現業務邏輯,因此結構非常清晰,擴展和修改都將非常容易,可以將擴展和修改維護的成本降低到很小的水平。
與目前業界比較常用的單純
ASP/JSP
代碼構建的
WebForm
方法相比,上述
WebForm
構建技術有明顯的優勢:
l???????
構建成本低,效率高
Jakarta Struts
標簽庫提供了一系列的標簽用于快速構建
JSP View
,標簽庫包括一般的
HTML
元素和控件
(html
標簽
)
,流程和邏輯控制的標簽
(logic
標簽
)
,
bean
操作標簽等等。這里以循環顯示所有的
Component
為例比較一下兩種方法的效率,假設
Component
對象數組可以從
request
中得到。
Logical
標簽:
<logic:iterate id="components" name="componentActionForms">
??????
?????? <bean:write name="components" property="component" />
</logic:iterate>
單純的
JSP
代碼:
<%
?????? ComponentActionForm[] components
= (ComponentActionForm[])request.getAttribute(“componentActionForms”);
????????????? For(int i=0;i<components.length;i++) {
???????????????????? out.println(components[i].getComponent);
}
%>
可以預見,顯示邏輯越復雜,用
Jakarta Struts
標簽庫構建的
JSP View
效率越高,結構也更清晰,構建和維護成本更低。詳細代碼請看附錄
IssueDetail.jsp
代碼。
l???????
可擴展性高
對于單純的
JSP/ASP
代碼構建的
View
而言,由于業務邏輯通常是在
JSP
頁面完成的,所以當業務邏輯改變或擴展之后,相應的
View
也必須改變;如果業務邏輯是在多個頁面完成的話,修改的成本更大,可擴展性更差。而用
Jakarta Struts
標簽庫構建的
View
,由于業務邏輯在相應的
Action
中完成,所以只需要修改相應的
Action
操作就可以了。尤其當
Action
復用程度比較高的時候,這種修改需要的工作量更小,而且
View
根本不需要修改,這種優勢也是
MVC
設計模式
Model
和
View
的分離所帶來的良好的可擴展性。
l???????
可重用性高
運用
Jakarta Struts
的
Logical
標簽,可以構建高度可復用的
WebForm
。雖然單純的
JSP/ASP
代碼技術也可以實現,但由此所帶來的構建、修改和維護成本將隨著邏輯的復雜度增加而急劇增長。比如上文提到的,運用
Jakarta Struts
的
Logical
標簽,我們很容易將
Issue
的創建、查看、修改、刪除顯示邏輯集中在一個
IssueDetail.jsp View
中完成。
l???????
可讀性高,結構清晰
Jakarta Struts
標簽和
HTML
代碼很接近,不需要額外的用
<%%>
等標簽包含起來,可讀性更高。而
Jakarta Struts
標簽集合了邏輯和流程控制,與
HTML
結合所構建的
JSP View
結構更清晰。下圖為
HTML
中內嵌
JSP
代碼和
Struts
標簽的代碼截圖,可以看到,使用
Struts
標簽的
View
結構更清晰,更易讀。
圖
14 HTML
中內嵌
JSP
代碼
圖15 HTML中內嵌Struts標簽代碼
posted on 2005-01-27 14:52
eamoi 閱讀(3364)
評論(0) 編輯 收藏 所屬分類:
Java 、
畢業設計文檔