webwork与struts的比较

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

特性Struts WebWork 1.x WebWork 2.x
Action classes Struts要求Action类继承一个抽象类. 这也说明
了Struts的一个常见问题: 针对抽象类编程而不
是接口.
Action必需实现
webwork.Action接
口. 还有其他接口可
以实现其他服务, 如
保存错误信息, 获取
本地化文本等.
ActionSupport类实
现了其中的一些接口,
也可以用作基类.
WebWork全部针对
接口编程, 这样很容
易插入你自己的实现.
与WebWork 1.x相同, Action必需实现
com.opensymphony.xwork.Action接
口, 还有一系列接口用于其他服务.
WebWork2提供ActionSupport 实现这
些接口.
线程模型Struts的Action必须是线程安全的, 因为它仅使
用一个示例处理全部请求. 这一限制导致Struts
的Action执行过程中使用的任何资源必须是线程
安全的或同步访问.
WebWork的Action
每一个请求使用一个
实例, 一次就不存在
线程安全问题. 实践
中, 每一次请求
Servlet容器都会生成
许多将被丢弃的对象,
多一个或几个对象并
没有证明会带来性能
问题或垃圾收集问题.
同上
对Servlet的
依赖性Struts的Actions依赖于Servlets, 因为执行时
使用(获取)了ServletRequest和
ServletResponse(而不是
HttpServletRequest和
HttpServletResponse). 绑定Servlets(虽然不
是HttpServlet)实际上就与Servlet容器绑定了,
而这种依赖关系并不需要. 例如, Servlet可以在
Web环境之外运行, 但JMS就不能.
WebWork的Action
没有绑定Web或其他
任何容器. WebWork
的action可以选择从
ActionContext中获
取request和
response, 但这不是
必须的并且仅当绝对
必要时才是用, 这并
不会与Web容器绑
定.
同上
可测试性
已经有许多测试Struts应用的策略, 但主要障碍
实际是Struts的Action与Web紧密的绑定在一起
(获取Request和Response对象). 着导致人们
经常在一个容器中测试Sstruts的Action, 这样做
既缓慢而又无法进行单元测试. 有一个Junit的扩
展包: Struts TestCase
(/)
WebWork的action
可以通过实例化
action, 设置属性并
执行的方式进行测试
同上, 但重点在于反转控制(Inversion of
Control)让测试变得更简单, 你可以在测
试中设置一个实现服务接口的Mock对象
进行测试, 而不需要设置服务注册表或使
用单件(static singleton)
FormBeans Struts需要为每个表单使用FormBean, 这产生
了大量的多余的类或者不得不使用DynaBean,
而这恰恰是这一限制的产物
WebWork 1.x允许直
接使用Action的属性
(也就是标准的
Javabean属性), 属
性可以包含丰富的对
象类型甚至可以有自
WebWork 2支持WebWork 1中的特性,
还加入了ModelDriven的Actions, 它允
许使用丰富的对象类型或域对象作为form
bean, 可以在Web页面中直接访问它的属
性, 这要好于作为活动属性的子属性进行
访问.
己的属性, 而这些属性都可以从Web页面中访问. WebWork也支持FormBean模式, 在"WW1:Populate Form Bean and access its value"中有关一这部分的介绍
表达式语言Struts 1.1集成了JSTL, 因此它使用JSTL EL.
该语言支持基本的对象图遍历, 但对集合和索引
的属性的支持要弱一些.
WebWork 1.x拥有自
己的表达式语言用以
访问值栈. 对集合以
及索引属性的支持很
基本但很好.
WebWork也可以直
接与JSTL共同使用,
参见WW1:Using
JSTL seamlessly
with WebWork
WebWork 2使用XW:Ognl, 这是一个非
常强大的表达式语言, 也可以访问值栈.
Ognl对集合和索引属性的支持非常强大.
Ognl还支持一些强大的特性如投射
(projections, 对集合的每一个元素调用
同一个方法并使用结果创建一个新的集
合), 挑选(selections, 使用一个选择表达
式过滤集合并返回一个子集), 列表构造和
lambda表达式(简化功能). Ognl还能访
问静态方法, 静态字段和构造方法.
WebWork2也能使用JSTL, 参见
WW1:Using JSTL seamlessly with
WebWork
将值绑定到视

Struts使用标准的JSP将对象绑定到
pageContext, 这使得视图与formBean紧密耦

WebWork设置了值
栈, WebWork标签库
可以从中十分灵活的
同上
动态查找所需的值, 而不需要将视图与数据类型紧密耦合. 这样就可以在很大的范围内复用视图.
类型转换
Struts的FormBeans属性通常都是字符串.
Struts使用Commons-Beanutils进行类型转
换. 每个类使用一个转换器, 但不允许为每个实
例配置不同的转换器. 获取一个有意义的类型转
换错误并显示给用户也是很难做到的.
WebWork 1.x使用
PropertyEditors进
行类型转换.
PropertyEditors针
对类型而不是Action,
但字段错误信息可以
加到活动的字段信息
表中并自动显示给用
户.
WebWork2使用Ognl进行类型转换, 并
为基本类型提供了转换器. 类型转换缺省
情况下使用上述转换器, 但也可以为每个
类的每个字段指定转换器. 类型转换错误
也有缺省错误信息但可以使用本地化机制
设置每个字段的信息, 字段错误信息可以
加到活动的字段信息表中并显示给用户.
前/后处理模
式必须创建一个继承基类Action的类来作为Action
前/后处理的代理, 这将导致类继承层次过深, 也
可能因为单继承的限制而无能为力
WW:Comparison to Struts#1
类继承
WebWork 2允许使用截取器模块化前/后
处理. 拦截器可以通过配置动态添加, 两者
之间没有任何耦合.
校验
Struts调用FormBean的validate()方法.
Struts用户通常使用Commons Validation进
行校验. 我对此不太了解, 因此仅提出几个问题:
由于FormBean属性一般都是字符串, 某些校验
方法是否会重复或无法做到?
WebWork1.x调用
Action的 validate()
方法, 你可以编写代
码校验, 也可以调用
外部校验框架(这显然
WebWork2可以使用WebWork1.x和
Struts的validate()方法, 还可以使用
XW:校验框架, 它由一个XWork截取器激
活. Xwork校验框架允许用XML格式编写
校验器, 可以为每个类提供一个缺省校验
器并在不同的校验环境中使用定制校验
Commons Validation是否能为同一个类设置不
同的校验环境? (我已被告知可以做到, 这是好事)
Commons Validation能否使用为对象属性类定
义的校验方式对子对象(sub-objects)进行校验?
与Sstruts相同) 器.Xwork校验框架由一个截取器激活因此
与Action类完全解藕. 还可以使用
VisitorFieldValidator将校验处理连接到
子属性(sub-properties, [与上文提到的
子对象相同).
对Action执
行过程的控制
以我的了解, Struts设置一个Action对象, 而你
对执行的顺序几乎无法控制. 要改变这一点, 我
认为需要编写自己的Servlet来自行处理分发
(dispatching)
由ActionFactory链
控制Action创建和初
始化的过程, 但需要
编写一个类
在这以问题上WebWork 2的截取器栈十
分有用. 设置Action的各方面功能都被转
移到截取器中实现(如设置参数, 校验等),
因此你可以依据截取器的功能控制每一个
Action的执行顺序. 例如你可能希望你的
IOC框架在request参数设置之前完成
Action配置, 反之亦然 - 也可以使用截取
器栈对每个包或每个类进行控制.
WebWork 2 : xwork.xml
This page last changed on May 26, 2004 by ctran.
示例
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xwork
PUBLIC
"-//OpenSymphony Group//XWork 1.0//EN"
"/xwork/xwork-1.0.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="default" extends="webwork-default">
<interceptors>
<interceptor-stack name="defaultComponentStack">
<interceptor-ref name="component"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
<action name="SimpleCounter" class="com.opensymphony.webwork.example.counter.SimpleCounter"> <result name="success" type="dispatcher">/success.jsp</result>
<interceptor-ref name="defaultComponentStack"/>
</action>
<!--
- Velocity implementation of the SimpleCounter. Also demonstrate a more verbose version of result element -->
<action name="VelocityCounter" class="com.opensymphony.webwork.example.counter.SimpleCounter"> <result name="success" type="velocity">
<param name="location">/success.vm</param>
</result>
<interceptor-ref name="defaultComponentStack"/>
</action>
<!--
- Different method can be used (processForm).
-->
<action name="formTest" class="com.opensymphony.webwork.example.FormAction" method="processForm" > <result name="success" type="dispatcher">/formSuccess.jsp</result>
<result name="invalid.token" type="dispatcher">/form.jsp</result>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="token"/>
</action>
</package>
</xwork>
活动
<action name="formTest" class="com.opensymphony.webwork.example.FormAction" method="processForm">
活动是WebWork的基本工作单元, 它正是定义了活动. 活动通常有一个请求(通常是点击按钮, 或提交表单). 主要的action元素有两部分, 友好的名字(在URL中引用, 如
saveForm.action)和对应的"处理(handler)"类.
可选的"method"属性告诉WebWork应当调用活动的哪个方法. 如果你不填写method属性, WebWork缺省调用execute(). 如果活动没有execute()方法, 也没有在xml
中指定method属性, WebWork将抛出异常.
同样, 你也可以在表单中指定"actionName!something"来告诉WebWork调用"doSomething"方法. 例如, "formTest!save.action"将调用FormAction的"save"
方法. 该方法必须是public且没有参数:
public String save() throws Exception
{
...
return SUCCESS;
}
活动的所有配置都可以用在"actionName!something"中(截取器, 结果类型等)
结果
<result name="missing-data" type="dispatcher">
<param name="location">/form.jsp</param>
<param name="parameterA">A</param>
<param name="parameterB">B</param>
</result>
Result元素告诉WebWork活动执行后下一步该做什么. "name"属性对应活动execute() 方法返回的结果代码. "type"属性表示使用哪个结果类型(参见结果类型). 可以使用
"param"元素向视图传递参数:
<result-types>
....
<result-type name="header"
class="com.opensymphony.webwork.dispatcher.HttpHeaderResult"/>
</result-types>
<result name="no-content" type="header">
<param name="status">204</param>
<param name="headers.customHeaderA">A</param>
<param name="headers.customHeaderB">B</param>
</result>
下面是WebWork内置的标准结果代码(定义在Action接口中), 包括:
Action.SUCCESS = "success";
Action.NONE = "none";
Action.ERROR = "error";
Action.INPUT = "input";
Action.LOGIN = "login";
你可以扩充你认为适合的结果代码(如"missing-data"). 大多数情况下你只需使用SUCCESS和ERROR, SUCCESS将前进到下一个页面.
如果你只需要指定"location"属性, 可以使用简写形式:
<result name="missing-data" type="dispatcher">/form.jsp</result>
参阅webwork-default.xml或Result Types以了解标准结果类型
截取器
截取器允许定义活动执行前后的代码. 截取器是编写Web应用的强大工具. 一些最常用的实现是:
•安全检查(确保用户已登陆)
•跟踪纪录(记录每一个活动)
•检查执行瓶颈(在活动前后启动计时器, 以检查应用瓶颈)
也可以将截取器连接起来创建一个截取器栈. 如果你想完成登陆检查, 安全检查, 并记录每个活动调用, 使用截取器栈会十分容易.
必须先定义截取器(给它命名)然后才能联接成栈:
<interceptors>
<interceptor name="security" class="com.mycompany.security.SecurityInterceptor"/>
<interceptor-stack name="defaultComponentStack">
<interceptor-ref name="component"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
要在活动中使用它们:
<action name="VelocityCounter" class="com.opensymphony.webwork.example.counter.SimpleCounter"> <result name="success">...</result>
<interceptor-ref name="defaultComponentStack"/>
</action>
注意: 可以引用拦截器或栈的名字
更多细节参见截取器.
视图
WebWork支持JSP和Velocity作为应用表示层. 本例使用JSP文件. Webwork附带了标签库(taglibs). 你可以在JSP中项组件一样使用标签库.下
面是form.jsp的片断:
<%@ taglib prefix="ww" uri="webwork" %>
<html>
<head><title>Webwork Form Example</title></head>
<body>
<ww:form name="myForm" action="'formTest'" namespace="/" method="POST">
<table>
<ww:textfield label="First Name" name="'formBean.firstName'" value="formBean.firstName"/>
<ww:textfield label="Last Name" name="'stName'" value="stName"/>
<ww:submit value="Save Form"/>
</table>
</ww:form>
</body>
处理经过如下:
1.WebWork监控以.action结尾的URI(定义在web.xml中)
2.WebWork在活动定义中查找活动formTest.
3.WebWork创建formTest并调用com.opensymphony.webwork.example.FormAction的方法processForm(定义在
xwork.xml中).
4.该方法处理成功并返回SUCCESS
5.WebWork将返回值SUCCESS转换成地址formSuccess.jsp(定义在b class="strong">xwork.xml中)并执行重定向.
包含
为了易于管理大规模开发活动(包含大量活动和配置), WebWork允许在xwork.xml中包含其他配置文件 :
<xwork>
<include file="webwork-default.xml"/>
<include file="user.xml"/>
<include file="shoppingcart.xml"/>
<include file="product.xml"/>
....
</xwork>
被包含文件必须与xwork.xml的格式相同(具有相同的doctype及其它)并放置在类路径中(通常位于/WEB-INF/classes或/WEB-INF/lib的jar文件
WebWork 2 : webwork-default.xml
This page last changed on Oct 23, 2004 by plightbo.
基本配置文件webwork-default.xml包含在webwork的jar文件中. 该文件可以包含在xwork.xml 中以便包含标准的配置信息而无需复制, 如下:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork
1.0//EN""/xwork/xwork-1.0.dtd"><xwork>
<include file="webwork-default.xml"/>
<package name="default" extends="webwork-default">
...
</package>
</xwork>
2.1.5版本的webwork-default.xml内容如下:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN""/xwork/xwork-1.0.dtd">
<xwork>
<package name="webwork-default">
<result-types>
<result-type name="dispatcher" class="com.opensymphony.webwork.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="redirect" class="com.opensymphony.webwork.dispatcher.ServletRedirectResult"/>
<result-type name="velocity" class="com.opensymphony.webwork.dispatcher.VelocityResult"/>
<result-type name="chain" class="com.opensymphony.xwork.ActionChainResult"/>
<result-type name="xslt" class="com.opensymphony.webwork.views.xslt.XSLTResult"/>
<result-type name="jasper"
class="com.opensymphony.webwork.views.jasperreports.JasperReportsResult"/>
<result-type name="freemarker" class="com.opensymphony.webwork.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="com.opensymphony.webwork.dispatcher.HttpHeaderResult"/>
<result-type name="stream" class="com.opensymphony.webwork.dispatcher.StreamResult"/> </result-types>
<interceptors>
<interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
<interceptor name="static-params"
class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
<interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
<interceptor name="component"
class="ponentInterceptor"/>
<interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
<interceptor name="token-session"
class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="servlet-config"
class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
<interceptor name="conversionError"
class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/>
<interceptor name="fileUpload" class="com.opensymphony.webwork.interceptor.FileUploadInterceptor"/>
<interceptor name="execAndWait"
class="com.opensymphony.webwork.interceptor.ExecuteAndWaitInterceptor"/>
<!-- Basic stack -->
<interceptor-stack name="defaultStack">
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="static-params"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack"> <interceptor-ref name="fileUpload"/>
<interceptor-ref name="defaultStack"/> </interceptor-stack>
<!-- Sample Inversion of Control stack --> <interceptor-stack name="componentStack"> <interceptor-ref name="component"/>
<interceptor-ref name="defaultStack"/> </interceptor-stack>
<!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack"> <interceptor-ref name="model-driven"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. --> <interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait"/>
</interceptor-stack>
<!-- A complete stack with all the common interceptors in place. Generally, this stack should be the one you use, though it
may process additional stuff you don't need, which could
lead to some performance problems. Also, the ordering can be switched around (ex: if you wish to have your components
before prepare() is called, you'd need to move the component
interceptor up -->
<interceptor-stack name="completeStack">
<interceptor-ref name="prepare"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="model-driven"/>
<interceptor-ref name="component"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="static-params"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
</package>
</xwork>
文件中定义了全部缺省结果和截取器, 还定义了一些截取器栈供你直接使用或作为特定截取器栈的基础. 注意: 包名字是"webwork-default".
Document generated by Confluence on Dec 14, 2004 16:37
web.xml文件简单明了, 易于配置.
Web.xml配置ServletDispatcher
应用中最常用的活动调用入口点是直接访问一个URL或使用表单向活动提交数据. 下例展示了如何配置ServletDispatcher来处理活动.
<!-- This entry is required to have the framework process calls to WebWork actions -->
<servlet>
<servlet-name>webworkDispatcher</servlet-name>
<servlet-class>com.opensymphony.webwork.dispatcher.ServletDispatcher</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webworkDispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
注意: 上面的例子假定活动使用".action"扩展名. 如果你向使用不同的扩展名, 将url-pattern元素改为你需要的扩展名并使用该扩展名修改调用代码.
WebWork 2 : 全局结果
全局结果允许定义一个结果映射, 它可以作为全部活动的缺省结果, 并自动被本包及所有扩展包中的活动继承. 换言之, 如果你想为多个活动指定同一个
结果, 就可以把它定义为全局结果.
示例
<package name="default">
....
<global-results>
<result name="login" type="dispatcher">
<param name="location">login.jsp</param>
</result>
</global-results>
<action name="foo" class="mypackage.fooAction">
<result name="success" type="dispatcher">bar.jsp</result>
</action>
<action name="submitForm" class="mypackage.submitFormAction"> <result name="success" type="dispatcher">submitSuccess.jsp</result> </action>
...
</package>
等同于
<package name="default">
....
<action name="foo" class="mypackage.fooAction">
<result name="success" type="dispatcher">bar.jsp</result>
<result name="login" type="dispatcher">login.jsp</result>
</action>
<action name="submitForm" class="mypackage.submitFormAction"> <result name="success" type="dispatcher">submitSuccess.jsp</result> <result name="login" type="dispatcher">login.jsp</result>
</action>
...
</package>。

相关文档
最新文档