本章我们会比较这两个框架的不同特性.与Struts1相比,Struts2是非常简单的,下面是Struts2的一些优秀特性 :
1.1 Servlet依赖性
由于Action在被调用时,HttpServletRequest和HttpServletResponse被传递到execute()方法中,Struts1中的Action对Servlet的API是有依赖性的.但如果在Struts2中,Action就不会对容器有依赖了,因为Action是由简单的POJO组成的.在Struts2中,servlet上下文以简单的Map的形式表现出来,这使得Action可以得到独立的测试.如果需要,Struts2也可以访问原始的请求与响应.不过,其他的框架元素减少或排除直接访问HttpServetRequest或HttpServletResponse的必要.
1.2 Action类
使用抽象类而不是接口设计是Struts1设计上的问题,这已经在Struts2中得到了解决.Struts1中的Action类需要继承框架中依赖的抽象基础类.但在Struts2中,Action类可能会也可能不会实现接口来启用可选的或者自定义的服务.在Struts2中,Action是不会依赖于容器的,因为它是由简单的POJO组成的.Struts2提供了一个基础的ActionSupport类来实现一些常用的接口.尽管这样,Action接口仍然不是必须要继承的,任何含有execute方法的POJO对象都可以当作Action对象来用.
1.3 验证
Struts1与Struts2都支持通过validate方法的手动验证.Struts1使用ActionForm中的validate方法或者通过扩展Commons Validator来进行校验.然而,Struts2支持通过Validate方法与Xwork校验框架的手动验证. Xwork框架支持验证链到子属性----使用为属性类文件和校验上下文定义的验证.
1.4 线程模型
在Struts1中,Action资源一定是线程安全或者同步的.所以Action是singletons并且线程安全的,一定只有一个Action类的实例处理该Action 的所有请求,singleton策略限制了Struts1的Action所能完成的,并且需要更加谨慎的开发.但是在Struts2中,Action对象对每一个请求都生成实例,所以在Struts2中不存在线程安全的问题.实际上,servlet容器对每个请求产生了很多浪费的对象,一个或多个对象不会使性能变得糟糕或者唤起垃圾回收器.
1.5 易测性
测试Struts1的程序会有些复杂.测试Struts1 Action的主要障碍就是因为它暴露了servlet的API.一个叫Struts TestCase 的第三方扩展,提供了一组Struts1测试用的模拟对象.但是在Struts2中,Action可以经由创建Action的实例,设置属性,和调用方法来得到测试.依赖注入同样使测试变得更容易.Struts2中的Action是简单的POJO并且独立于框架,从此,Struts2中的测试是很简单的.
1.6 获取输入
Struts1使用ActionForm来捕获输入.而且所有的ActionForm需要继承一个框架依赖的基类.由于JavaBean不能当作ActionForm来用,开发人员不得不创建冗繁的类来获取输入.不过Struts2使用Action属性(例如输入属性不依赖于底层框架)这避免了需要创建第二个输入对象,从此冗繁减少了.此外在Struts2中,Action的属性可以通过标签在web页面中得到访问.Struts2同样支持ActionForm模式,POJO表单对象和POJO Action.甚至富对象类型,包括业务或域对象,都可以被当作输入/输出对象来使用.
1.7 表达式语言
Struts1与JSTL整合,所以它使用JSTL表达式语言.Struts1的表达式语言含有遍历图表的基础对象,但是在集合和索引属性的支持上表现不好.Struts2同样支持JSTL,但是它也支持一种更强大且灵活的表达式语言----“对象图标记语言”(OGNL)
1.8 将绑定值到视图中
在视图层,Struts1使用标准的JSP来绑定对象(在模型层被处理的)到页面上下文来进行访问.然而Struts2使用一种叫做值栈的技术,这使得标签可以访问值而不需将视图与正在呈递的对象类型连接起来.值栈允许重用一些属性名相同但类型不同的视图类型.
1.9 类型转换
通常Struts1的ActionForm属性都是String型的.Struts1使用Commons-Beanutils进行类型转换.这些针对每一个类的类型转换无法为每一个实例配置.然而Struts2使用OGNL来进行类型转换.框架包含了针对基础类型,常见对象类型与原始类型的转换器.
1.10 Action执行的控制
Struts1支持对每一个模块的请求处理器的分离(生命周期),但是同一模块下的所有Action必须共享相同的生命周期.Struts2支持通过拦截器栈为每一个Action创建不同的生命周期.自定义栈可以视需要对不同的Action使用.