| Feature |
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类实现这些接口. |
| Threading Model |
Struts Actions必须是线程安全的,因为Action在处理所有的请求时都只有一个实例.这要求和Struts Actions一起处理的所有资源都要是线程安全的,或者是同步的. |
WebWork Actions 为每个请求初始化一个实例, 这样就解决了线程安全的问题. 实际上, Servlet 容器每次处理请求时,都会生成许多将被丢弃的对象,但并没有证据证明更多的对象会产生性能或者垃圾回收问题 |
同WebWork 1.x |
| Servlet Dependency |
Struts Actions 依赖于Servlets ,因为Struts Actions 在执行的时候使用了ServletRequest and ServletResponse (并不是HttpServletRequest and HttpServletResponse).这种对于Servlets的依赖事实上是对Servlets容器的依赖,这样的依赖是不必要的.例如, Servlet可以在Web环境之外运行, 但JMS就不能. |
WebWork Actions 不依赖于web和容器 WebWork actions可以从ActionContext访问request 和response对象,但是这不是必须的,并且最好在绝对需要的时候才去做,以避免对于web层的依赖. |
同WebWork 1.x |
| Testability |
已经有许多测试Struts应用的策略,其中最大的障碍是由于Struts Actions对于web层的紧密依赖.(使用Request和Response对象).这导致人们需要在容器内测试Struts Actions.这样做即缓慢又称不上是单元测试. 有一个Junit的扩展 : Struts TestCase (http://strutstestcase.sourceforge.net/ ) |
WebWork actions 通过初始化,设置属性,运行你的Action可以很容易的进行测试 |
同WebWork 1.x, 由于加强了控制翻转(Inversion of Control)的应用使得测试更加简单.你不需要注册服务或者使用静态单例(static singleton),仅仅向你的Action里注入实现服务接口的模拟对象(Mock)就可以进行测试 |
| FormBeans |
Struts需要对每个表单创建FormBeans, 使得要么增加许多额外的类,要么使用DynaBeans, 而DynaBeans恰恰是这一限制的产物 |
WebWork 1.x 允许你像取得一般的Javabeans的属性那样直接取得你Action中的所有属性, 属性可以包含丰富的对象类型甚至可以有自己的属性, 而这些属性都可以从Web页面中访问WebWork也支持FormBean模式, 在 "Populate Form Bean and access its value "中,有相关的论述 |
WebWork 2 拥有WebWork 1相同的特性, 除此之外,还添加了模型驱动(ModelDriven)Action.模型驱动Action允许你把富对象类型或者是域对象当做form bean使用,这样它的属性可以在web页面上直接访问,而不用做为Action的属性的一个子属性来访问. |
| Expression Language |
Struts 1.1 集成 JSTL, 因此可以在Struts中使用JSTL EL. 这种EL语言只能进行基本的对象图的遍历,对于集合和索引属性方面的支持要弱一些. |
WebWork 1.x拥有自己的表达式语言用以访问值堆栈. 对集合以及索引属性的提供很基本的支持但工作的很好.WebWork也能和JSTL一起工作 |
WebWork 使用Ognl,一个非常强大的表达式语言, 可以访问值堆栈. Ognl 对集合和索引属性提供强有力的支持. Ognl 还拥有其他强大的特性,例如projections (调用集合中所有成员的相同方法,把结果构造成一个新的集合), selections (用一个选择表达式过滤一个集合并返回得到的子集), list construction, and lambda expressions (可以重用的简单函数). Ognl 也可以访问静态方法,静态字段以及类的构造器. WebWork2也能使用JSTL, 参见Using JSTL seamlessly with WebWork |
| Binding values into views |
Struts采用标准的JSP机制来把对象绑定到页面(page context),这使得视图与formBean紧密耦合 |
WebWork 使用可以被WebWork的标签库直接访问的值堆栈, 显得更加灵活并且不会把视图和你要生成的类型绑定起来.这样就可以在很大的范围内复用视图. |
同WebWork 1.x |
| Type Conversion |
Struts FormBeans 的属性通常都是String类型的. Struts使用Commons-Beanutils进行类型转换.每个类使用一个转换器, 但不允许为每个实例配置不同的转换器. 所以很难得到一个有意义的类型转换错误并把它显示给用户. |
WebWork 1.x应用 PropertyEditors来进行类型转换. PropertyEditors针对类型而不是Action, 但是字段的错误信息会被加进Action中的字段错误表(field error map)中,并且自动的显示给用户. |
WebWork2 应用Ognl 进行类型转换,Ognl提供针对基本类型的转换器. 类型转换缺省情况下使用上述转换器, 但也可以为每个类的每个字段指定转换器. 类型转换有默认的错误消息,但是也可以应用WW2的本地化机制来为每个类的每个字段设置一个错误消息.这些消息会被装载到Action的字段错误消息中. |
| Modular Before & After Processing |
必须创建一个继承基类Action的类来作为Action前/后处理的代理, 这会导致类继承层次过深和对多重继承的限制 Comparison to Struts#1 |
类层次 |
WebWork 2 允许你在拦截器里面模块化这种处理.拦截器可以通过配置动态的使用而无需和Action类产生耦合. |
| Validation |
Struts调用FormBean中的validate()方法,Struts的使用者一般使用Commons Validation来进行验证.我对此不太了解, 因此仅提出几个问题:
由于FormBean的属性一般是String类型的,某些校验方法是否会重复或无法做到?
Commons Validation是否能为同一个类设置不同的校验环境?(我已被告知可以做到, 这是好事)
Commons Validation能否使用为对象属性类定义的校验方式对子对象(sub-objects)进行校验? |
WebWork1.x 调用Action中的validate()方法, 即可以手工编写验证也可以调用外部的验证框架(这显然和Struts相同) |
WebWork2可以使用类似与WebWork和Struts那样使用validate()方法来进行验证,也可以使用这样一个由XWork拦截器激活的验证框架. Xwork验证框架允许用XML格式编写校验器,根据不同的上下文增加自定义验证. Xwork验证框架通过拦截器生效因此和Action完全解耦. Xwork验证框架也允许你使用VisitorFieldValidator对子属性进行持续验证,VisitorFieldValidato利用了为类的属性和上下文定义的验证信息. |
| Control Of Action Execution |
就我所知,Struts为你设置好了Action对象,因此你很难去控制执行的顺序. 为了改变执行的顺序我认为 你需要写一个自己的Servlet来处理你需要的分派规则 |
Action工厂(ActionFactory)控制了Action构建和初始化的顺序,但需要编写一个类 |
在这点上WebWork 2的拦截器堆栈显得特别强大. Action设置的方方面面都被移到了拦截器的实现中(例如从web设置参数,验证等等), 所以你能根据它们执行顺序控制每一个Action. 例如你想在参数从request设置之前用你的IOC框架来配置action或者进行相反的操作, - 也可以使用截取器栈对每个包或每个类进行控制. |