在
Struts
的控制邏輯中,
Controller
的
ActionServlet
、
RequestProcessor
是由
Struts
自身實現(xiàn)的。用戶需要實現(xiàn)的是
Model
的
Action
的
Perform
或者
Execute
方法。我們定義了兩個
Action
:
IssueAction
和
MainAction
,在
Action
中根據(jù)參數(shù)
action
的類型判斷并實現(xiàn)各種邏輯操作。下面以
IssueAction
、
IssueActionForm
、
IssueDetail.jsp
為例說明
LPMT
中的控制結(jié)構(gòu)實現(xiàn)。
在
IssueAction
中,定義參數(shù)
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
根據(jù)需要初始化對象,調(diào)用
IssueBean
的方法完成相應(yīng)的業(yè)務(wù)邏輯操作,最后返回相應(yīng)的
ActionMapping
對象。
在
IssueActionForm
中,處理對應(yīng)表單頁面的所有項之外,我們另外定義了一個
actionType
參數(shù),來保存并傳遞
Action
的操作類型。
private String actionType = "create";
在
Action
判定操作類型之后,要設(shè)置對應(yīng)
IssueActionForm
對象的
actionType
值。比如:
issueActionForm.setActionType(action);
issueDataActionForm.setActionType(action);
在
IssueAction
對應(yīng)的
IssueDetail.jsp
頁面中,需要根據(jù)當(dāng)前
IssueActionForm
參數(shù)
actionType
的值來判斷當(dāng)前操作類型,繼而實現(xiàn)相應(yīng)的顯示邏輯。比如:
當(dāng)
actionType = “create”
時,操作類型為新建
Issue
,此時顯示一張空白表單,初始化
Component
、
Environment
等可選項;當(dāng)
actionType = “edit”
時,操作類型為編輯
Issue
,此時要載入表單值,如
issueId
,
title
,
Component
等等;當(dāng)
actionType = “viewDetail”
時,操作類型為查看
Issue
內(nèi)容。這里使用
<logic:equal>
標(biāo)簽來實現(xiàn)控制顯示邏輯,用
<logic:present>
和
<logic:notPresent>
判斷對應(yīng)的
issueActionForm
是否已經(jīng)載入頁面。我們以顯示
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
系統(tǒng)設(shè)計中,
WebForm
作為直接呈現(xiàn)給客戶端的
View
,其實現(xiàn)技術(shù)一直為業(yè)界所關(guān)注。從最初的單純的
HTML
,到后來的
CGI
、
PERL
,到最近的
ASP
、
JSP
,到目前的標(biāo)簽庫,業(yè)界一直在尋找一種能夠快速開發(fā)、靈活、高效率、可重用的技術(shù)來實現(xiàn)業(yè)務(wù)邏輯呈現(xiàn)。在
LPMT
中,我們采用
HTML
結(jié)合
Jakarta Struts
標(biāo)簽的技術(shù)來實現(xiàn),
JSP
頁面作為單純的
View
使用,而業(yè)務(wù)邏輯完全由
Action
完成。同樣是運行于
Server
端的技術(shù),與單純的
ASP
、
JSP
技術(shù)相比,運用
Jakarta Struts
標(biāo)簽庫構(gòu)建的
JSP
頁面結(jié)構(gòu)更清晰,可重用性和擴(kuò)展性更優(yōu)秀。
Jakarta Struts1.0
的標(biāo)簽庫包括:
l???????
Bean
標(biāo)簽:
提供一組操作標(biāo)簽,用于在必要的時候封裝邏輯,使用JavaBeans、HTTP Cookies、HTTP Headers。這些標(biāo)簽封裝在文件名為struts-bean.tld的標(biāo)簽包中。
l???????
Logical
標(biāo)簽:
提供一組用來在JSP頁中有條件地產(chǎn)生輸出文本,在對象集合中循環(huán)從而重復(fù)地產(chǎn)生輸出文本,以及應(yīng)用程序流程控制的標(biāo)簽。Logical標(biāo)簽庫定義的標(biāo)記能夠執(zhí)行條件邏輯、重復(fù)循環(huán)、轉(zhuǎn)發(fā)/重定向等功能,可以完全替代scriptlet。這些標(biāo)簽封裝在文件名為struts-logic.tld的標(biāo)簽包中。
l???????
HTML
標(biāo)簽:
用來生成HTML標(biāo)簽,顯示表單元素、控件及其數(shù)據(jù),使用會話ID對URL進(jìn)行編程,以及顯示錯誤信息。這些標(biāo)簽封裝在文件名為struts-html.tld的標(biāo)簽包中。
l???????
Templete
標(biāo)簽:
提供一組用于定義可重用的模板視圖的標(biāo)簽,包括:<template:get/>、<template:insert/>、<template:put>。這些標(biāo)簽被封裝在文件名為struts-template.tld的標(biāo)簽包中。
Struts1.1
還引入了struts-nested和struts-tiles兩個標(biāo)簽庫。在LPMT中,我們采用了Struts1.0的四個標(biāo)簽庫。
WebForm
即是通常
MVC
設(shè)計模式中的
View
。在
LPMT
中,
View
由通過
HTML
和
Struts
標(biāo)簽構(gòu)建的
JSP
頁面充當(dāng)。
JSP
頁面作為
View
使用,只負(fù)責(zé)顯示業(yè)務(wù)邏輯的處理結(jié)果,并不負(fù)責(zé)業(yè)務(wù)邏輯處理。為使
View
具有較高的可復(fù)用性,通常將多個邏輯顯示集合在一個
View
完成;為使
View
具有較高的穩(wěn)定性,
JSP
頁面應(yīng)該保留通用的接口,即使
Action
的業(yè)務(wù)邏輯改變了,
View
仍然不需要修改。另外,為使
View
具有較高的可擴(kuò)展性和可維護(hù)性,降低未來可能的維護(hù)成本,
View
結(jié)構(gòu)應(yīng)該清晰易讀。以
IssueDetail.jsp
為例說明
WebForm
的
Jakarta Struts
技術(shù)實現(xiàn)。
IssueDetail.jsp
的設(shè)計需求是要實現(xiàn)
Issue
創(chuàng)建、查看、修改、刪除的頁面顯示。當(dāng)操作類型為創(chuàng)建
—
“
create
”時,
View
應(yīng)該初始化一張空白的
Issue
表單,等待用戶輸入;當(dāng)操作類型為查看
—
“
viewDetail
”時,
View
應(yīng)該把相應(yīng)的
Issue
的值及其
IssueData
、
ChangeLog
顯示出來,內(nèi)容為不可編輯;當(dāng)操作類型為修改時,
View
表單應(yīng)該初始化相應(yīng)
Issue
的值并于相應(yīng)的
HTML
控件集合,內(nèi)容為可編輯;當(dāng)操作類型為刪除
—
“
delete
”時,
View
不顯示或者顯示
Issue
的內(nèi)容,不可編輯。
為實現(xiàn)上述上述邏輯,我們采用
<logic:equal>
標(biāo)簽,通過判斷
issueActionForm
對象的
actionType
參數(shù)的
value
值來判斷操作類型,繼而實現(xiàn)相應(yīng)的顯示邏輯。以顯示
Issue
的
description
值為例,代碼實現(xiàn)如下:
<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
通用性設(shè)計方面,
IssueDetail.jsp
通過使用
<logic:present>
和
<logic:notPresent>
標(biāo)簽判斷對象
issueActionForm
是否已經(jīng)加載到
scope
以及加載進(jìn)來的
issueActionForm
的
actionType
等屬性值來完成邏輯顯示。這意味著當(dāng)
Action
完成相應(yīng)的業(yè)務(wù)邏輯之后,在返回指向
IssueDetail.jsp
的
ActionMapping
對象之前,只需要把相應(yīng)的
IssueActionForm
對象實例加載到如
Request
、
Session
或者
PageContext
即任何一個
scope
里面就可以了,不需要在
URL
中傳遞任何參數(shù)。
比如在
IssueAction
中,當(dāng)操作類型為查看相應(yīng)
Issue
的詳細(xì)內(nèi)容時,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=viewDetail&issueId=...
,
IssueAction
先取得
URL
傳遞過來的
issueId
參數(shù)值,然后通過
IssueBean.getIssueById
方法取得對應(yīng)的
IssueActionForm
對象實例
issueActionForm
,設(shè)置
issueActionForm
對象的
actionType
參數(shù),把
issueActionForm
放到
httpServletRequest
對象中,最后設(shè)置轉(zhuǎn)向參數(shù)
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";
???
????? }
}
當(dāng)操作類型為新建一個
Issue
實例的時候,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=create
,
IssueAction
取得
typeActionForm
對象數(shù)組、
componentActionForm
對象數(shù)組、
flagActionForm
對象數(shù)組、
environmentActionForm
對象數(shù)組和
priorityActionForm
對象數(shù)組并放到
httpServletRequest
對象中,最后設(shè)置轉(zhuǎn)向參數(shù)
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";
}
當(dāng)操作類型為編輯修改一個
Issue
實例的時候,
URL
請求為
http://localhost:8000/issuecontrol/issueAction.do?action=edit&issueId
=...
,
IssueAction
根據(jù)取得的參數(shù)
issueId
的值取得相應(yīng)的
IssueActionForm
對象實例
issueActionForm
,設(shè)置
issueActionForm
的參數(shù)
actionType
的值,取得
typeActionForm
對象數(shù)組、
componentActionForm
對象數(shù)組、
flagActionForm
對象數(shù)組、
environmentActionForm
對象數(shù)組和
priorityActionForm
對象數(shù)組并將所有對象實例放到
httpServletRequest
對象中,最后設(shè)置轉(zhuǎn)向參數(shù)
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
只負(fù)責(zé)邏輯顯示,而不需要實現(xiàn)業(yè)務(wù)邏輯,因此結(jié)構(gòu)非常清晰,擴(kuò)展和修改都將非常容易,可以將擴(kuò)展和修改維護(hù)的成本降低到很小的水平。
與目前業(yè)界比較常用的單純
ASP/JSP
代碼構(gòu)建的
WebForm
方法相比,上述
WebForm
構(gòu)建技術(shù)有明顯的優(yōu)勢:
l???????
構(gòu)建成本低,效率高
Jakarta Struts
標(biāo)簽庫提供了一系列的標(biāo)簽用于快速構(gòu)建
JSP View
,標(biāo)簽庫包括一般的
HTML
元素和控件
(html
標(biāo)簽
)
,流程和邏輯控制的標(biāo)簽
(logic
標(biāo)簽
)
,
bean
操作標(biāo)簽等等。這里以循環(huán)顯示所有的
Component
為例比較一下兩種方法的效率,假設(shè)
Component
對象數(shù)組可以從
request
中得到。
Logical
標(biāo)簽:
<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);
}
%>
可以預(yù)見,顯示邏輯越復(fù)雜,用
Jakarta Struts
標(biāo)簽庫構(gòu)建的
JSP View
效率越高,結(jié)構(gòu)也更清晰,構(gòu)建和維護(hù)成本更低。詳細(xì)代碼請看附錄
IssueDetail.jsp
代碼。
l???????
可擴(kuò)展性高
對于單純的
JSP/ASP
代碼構(gòu)建的
View
而言,由于業(yè)務(wù)邏輯通常是在
JSP
頁面完成的,所以當(dāng)業(yè)務(wù)邏輯改變或擴(kuò)展之后,相應(yīng)的
View
也必須改變;如果業(yè)務(wù)邏輯是在多個頁面完成的話,修改的成本更大,可擴(kuò)展性更差。而用
Jakarta Struts
標(biāo)簽庫構(gòu)建的
View
,由于業(yè)務(wù)邏輯在相應(yīng)的
Action
中完成,所以只需要修改相應(yīng)的
Action
操作就可以了。尤其當(dāng)
Action
復(fù)用程度比較高的時候,這種修改需要的工作量更小,而且
View
根本不需要修改,這種優(yōu)勢也是
MVC
設(shè)計模式
Model
和
View
的分離所帶來的良好的可擴(kuò)展性。
l???????
可重用性高
運用
Jakarta Struts
的
Logical
標(biāo)簽,可以構(gòu)建高度可復(fù)用的
WebForm
。雖然單純的
JSP/ASP
代碼技術(shù)也可以實現(xiàn),但由此所帶來的構(gòu)建、修改和維護(hù)成本將隨著邏輯的復(fù)雜度增加而急劇增長。比如上文提到的,運用
Jakarta Struts
的
Logical
標(biāo)簽,我們很容易將
Issue
的創(chuàng)建、查看、修改、刪除顯示邏輯集中在一個
IssueDetail.jsp View
中完成。
l???????
可讀性高,結(jié)構(gòu)清晰
Jakarta Struts
標(biāo)簽和
HTML
代碼很接近,不需要額外的用
<%%>
等標(biāo)簽包含起來,可讀性更高。而
Jakarta Struts
標(biāo)簽集合了邏輯和流程控制,與
HTML
結(jié)合所構(gòu)建的
JSP View
結(jié)構(gòu)更清晰。下圖為
HTML
中內(nèi)嵌
JSP
代碼和
Struts
標(biāo)簽的代碼截圖,可以看到,使用
Struts
標(biāo)簽的
View
結(jié)構(gòu)更清晰,更易讀。
圖
14 HTML
中內(nèi)嵌
JSP
代碼
圖15 HTML中內(nèi)嵌Struts標(biāo)簽代碼
posted on 2005-01-27 14:52
eamoi 閱讀(3374)
評論(0) 編輯 收藏 所屬分類:
Java 、
畢業(yè)設(shè)計文檔