在
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 阅读(3357)
评论(0) 编辑 收藏 所属分类:
Java 、
毕业设计文档