Struts作为MVC 2的Web框架,自推出以来不断受到开发者的追捧,得到广泛的应用。作为最成功的Web框架,Struts自然拥有众多的优点:MVC 2模型的使用、功能齐全的标志库(Tag Library)、开放源代码。
但是,正所谓“没有最好,只有更好”,Struts1.x自身也有不少的缺点:需要编写的代码过多,容易引起“类爆炸”、单元测试困难。这些缺点随着Web的发展越来越明显。这就促生了Struts 2,它的诞生能很好的解决上述问题。
在本文中,笔者将对Struts2和Struts1.x这两种框架进行详细的比较。比较将涉及到这两种框架的Action、验证、类型转换及如何开发等方面的内容。希望通过这样的比较,让读者了解这两种框架各自的特点,以便于在自己的项目中,根据实际情况,尽快的过渡到Struts2的时代。本文的内容基于Struts2.0.6。
一、 引言
Struts的第一个版本是在2001年5月份发布的。它的最初设想是通过结合JSP和Servlet,使Web应用的视图和业务/应用逻辑得以清晰地分离开来。在Struts之前,最常见的做法是在JSP中加入业务和应用逻辑,或者在Servlet中通过println()来生成视图。
自从第一版发布以来,Struts实际上已成为业界公认的Web应用标准。它的炙手可热也为自己带来了改进和变更,所以不但要跟上对Web应用框架不断变化的需求,而且要与日渐增多竞争激烈的众多框架的特性相融合。
到最后,产生了几个下一代Struts的解决方案。其中两个最受瞩目的方案是Shale和Struts Ti。Shale是一个基于构件的框架,并在最近成为Apache的顶级项目。而Struts Ti则是在Struts的成功经验基础上继续坚持对前端控制器(Front Controller)和MVC(model-view-controller)模式进行改进。
WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想、概念和功能,但和原Struts代码并不兼容。WebWork是一个成熟的框架,经过了好几次重大的改进与发布。
在2005年12月,WebWork与Struts Ti宣布合并。与此同时,Struts Ti改名为Struts Action Framework 2.0,成为Struts真正的继承者。
最后要注意的是,并不是说Struts或WebWork项目已经停止开发了。由于人们对这两个项目的兴趣仍然很高,而且也有很多开发者仍然愿意使用它们,因此这两个项目还在继续开发中,继续修复Bug,改进功能和继续添加新功能。
二、 Action的区别
对于有着丰富的Struts1.x开发经验的朋友来说,都十分的清楚Action是整个Struts框架的核心内容,当然Struts2也不例外。不过,Struts1.x与Struts2的Action模型很大的区别。
Struts2和Struts1.x的差别,最明显的就是Struts2是一个pull-MVC架构。这是什么意思呢?从开发者角度看,就是说需要显示给用户的数据可以直接从Action中获取,而不像Struts1.x那样,必须把相应的Bean存到Page、Request或者Session中才能获取。Struts1.x 必须继承org.apache.struts.action.Action或者其子类,表单数据封装在FormBean中。Struts 2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过Getter和Setter获取(如下面的ActionForStruts2的代码示例)。
虽然,在理论上Struts2的Action无须实现任何接口或者是继承任何的类,但是,在实际编程过程中,为了更加方便的实现Action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并且重载(Override)此类里的String execute()方法。如下所示:
package ActionDiffer; import java.text.DateFormat; import java.util.Date; import com.opensymphony.xwork2.ActionSupport; public class ActionForStruts2 extends ActionSupport { private String message; public String getMessage() { return message; } @Override public String execute() { message = " This is hello from strtuts2. Now is: " + DateFormat.getInstance().format(new Date()); return SUCCESS; } }
首先,从ActionForStruts2可以看出,返回的对象不是ActionForward,而是String。如果你不喜欢以字符串的形式出现在你的代码中,有个Helper接口Action可以以常量方式提供常见结果,如“success”、“none”、“error”、“input”和“login”。
另外, 按照惯例,在Struts1.x中只有“execute”方法能调用Action, 但在Struts2中并非必要,任何声明为public String methodName() 方法,都能通过配置来调用Action。
最后,和Struts1.x最大的革命性的不同是,Struts2处理Action过程中调用的方法(“execute”方法)是不带参数的。那如何获取所需要的对象呢?答案是使用IoC(反转控制,Inversion of Control),也叫“依赖注入(Dependency Injection)”的模式(想更多地了解这方面信息请看Martin Fowler的文章http://www.martinfowler.com/articles/injection.html)。Spring框架使得这个模式流行起来,然而Struts2的前身(WebWork)也同时应用上了这个模式。
三、 IoC
IoC(Inversion of Control,以下译为控制反转),随着Java社区中轻量级容器(Lightweight Contianer)的推广而越来越为大家耳熟能详。在此,无需再多费唇舌来解释“什么是控制反转”和“为什么需要控制反转”。因为互联网上已经有非常多的文章对诸如此类的问题作了精彩而准确的回答。读者可以去读一下Rod Johnson和Juergen Hoeller合著的《Expert one-on-one J2EE Development without EJB》或Martin Fowler所写的《Inversion of Control Containers and the Dependency Injection pattern》。
众所周知,Struts2是以Webwork 2作为基础发展出来。而在Webwork 2.2之前的Webwork版本,其自身有一套控制反转的实现,Webwork 2.2在Spring 框架的如火如荼发展的背景下,决定放弃控制反转功能的开发,转由Spring实现。值得一提的是,Spring确实是一个值得学习的框架,因为有越来越多的开源组件(如iBATIS等)都放弃与Spring重叠的功能的开发。因此,Struts2推荐大家通过Spring实现控制反转。
为了更好地了解反转控制,下面来看一个例子,如何利用IoC在Action处理过程中可以访问到当前请求HttpServerRequest对象。
在例子中,使用的依赖注入机制是接口注入。就如其名称一样,接口注入需要的是已经被实现了的接口。这个接口包含了相应属性的setter,为Action提供值。例子中使用了ServletRequestAware接口,如下:
public interface ServletRequestAware { public void setServletRequest(HttpServletRequest request); }
当继承这个接口后,原本简单的Action看起来有点复杂了,但是这时可以获取HttpServerRequest对象来使用了。
public class IoCForStruts2 implements ServletRequestAware { private HttpServletRequest request; public void setServletRequest(HttpServletRequest request) { this.request = request; } public String execute() throws Exception { // 可以开始使用request对象进行工作了 return Action.SUCCESS; } }
看起来现在这些属性是类级别的,并不是线程安全的,会出现问题。其实在Struts2里并没有问题,因为每个请求过来的时候都会产生一个新的Action对象实例,它并没有和其他请求共享一个对象,所以不需要考虑线程安全问题。
四、 拦截器
Interceptor(以下译为拦截器),在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取action中可重用的部分的方式。
Struts1.x的标准框架中不提供任何形式的拦截器,虽一个名为SAIF的附加项目则实现了这样的功能,但它的适用的范围还很有限。
拦截器是Struts2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、转换器,校验等。谈到拦截器,还有一个流行的词——拦截器链(Interceptor Chain,在Struts2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
Struts 2的拦截器实现相对比较简单。当请求到达Struts2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一一地调用列表中的拦截器。
Struts 2已经提供丰富多样功能齐全的拦截器实现。读者可以到struts2-all-2.0.6.jar或struts2-core-2.0.6.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。
作为“框架(framework)”,可扩展性是不可缺少的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。
五、 Struts2和Struts1.x的全面比较
为了对Struts2和Strtus1.x进行全面的比较,让读者了解这两种框架各自的优缺点,以便于在自己的项目中,根据实际情况,选择合适的框架,对它们两者进行比较,总结了如下表分析比较。
特性
|
Struts1.x
|
Struts2
|
Action类
|
Struts1.x要求Action类要扩展自一个抽象基类。Struts1.x的一个共有的问题是面向抽象类编程而不是面向接口编程。
|
Struts2的Action类实现了一个Action接口,连同其他接口一起来实现可选择和自定义的服务。Struts2提供一个名叫ActionSupport的基类来实现一般使用的接口。当然,Action接口不是必须的。任何使用execute方法的POJO对象可以被当作Struts 2的Action对象来使用。
|
线程模型
|
Struts1.x Action类是单例类,因为只有一个实例来控制所有的请求。单例类策略造成了一定的限制,并且给开发带来了额外的烦恼。Action资源必须是线程安全或者同步的。
|
Struts2 Action对象为每一个请求都实例化对象,所以没有线程安全的问题。(实践中,servlet容器给每一个请求产生许多丟弃的对象,并且不会导致性能和垃圾回收问题)。
|
Servlet 依赖
|
Struts1.x的Action类依赖于servlet API,当Action被调用时,以HttpServletRequest和HttpServletResponse作为参数传给execute方法。
|
Struts2的Action和容器无关。Servlet上下文被表现为简单的Maps,允许Action被独立的测试。Struts2的Action可以访问最初的请求(如果需要的话)。但是,尽可能避免或排除其他元素直接访问HttpServletRequest或HttpServletResponse。
|
易测性
|
测试Struts1.x的主要问题是execute方法暴露了Servlet API这使得测试要依赖于容器)。第三方的扩展,如Struts TestCase,提供了一套Struts1的模拟对象(来进行测试)。
|
Struts2的Action可以通过初始化、设置属性、调用方法来测试。依赖注入的支持也是测试变得更简单。
|
捕获输入
|
Struts1.x使用ActionForm对象来捕获输入。象Action一样,所有的ActionForm必须扩展基类。因为其他的JavaBean不能作为ActionForm使用,开发者经常创建多余的类来捕获输入。DynaBeans可以被用来作为替代ActionForm的类来创建。但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean)。
|
Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种ModelDriven 特性简化了taglib对POJO输入对象的引用。
|
表达式语言
|
Struts1.x整合JSTL,所以它使用JSTL的表达式语言。表达式语言有基本的图形对象移动,但是对集合和索引属性的支持很弱。
|
Struts2使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL)。
|
将值绑定到页面
|
Struts1.x使用标准JSP机制来绑定对象到页面上下文。
|
Struts2使用“ValueStack”技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
|
类型转换
|
Struts1.x的ActionForm属性经常都是String。Struts 1.x使用Commons-Beanutils来进行类型转换。转换每一个类,而不是为每一个实例配置。
|
Struts2使用OGNL进行类型转换。提供基本和常用对象的转换器。
|
验证
|
Struts1.x支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
|
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
|
Action执行控制
|
Struts1.x支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
|
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。
|
六、 结论
前面已经简要介绍了Struts2的起源,并详细对比了Struts2和Struts1.x的差异,读者应该对Struts2的基础有所了解了——包括高层的框架概念和基础的请求流程,并理解Struts1.x和Struts2两者之间在Action方面的差别,Struts2加强了对拦截器与IoC的支持,而在Struts1.x中,这些特性是很难想象的。
同时,读者应该明白:Struts2是WebWork的升级,而不是Struts 1.x的升级。虽然Struts 2提供了与Struts1.x的兼容,但已经不是Struts1.x的升级。对于已有Struts1.x开发经验的开发者而言,Struts1.x的开发经验对于Struts2并没有太大的帮助;相反,对于已经有WebWork开发经验的开发者而言,WebWork的开发经验对Struts2的开发将有很好的借鉴意义。
分享到:
相关推荐
Struts1_x与Struts2的深度比较
牛牧的"Struts2.x深入浅出"教程是针对这个框架的深度解析,主要帮助开发者理解并熟练掌握Struts2的核心概念和实践技巧。 在第二部分中,我们首先会接触到`struts2_GetFromData`,这部分主要讲解了如何从HTTP请求中...
总之,深入研究“struts-1.2.9-src.zip”中的源代码,不仅可以提升对Struts框架的理解,还能提高Java Web开发技能,对于维护和升级老系统,或是对MVC架构有深度需求的开发者来说,都是非常有益的。
Struts框架,作为Java Web开发领域的一个里程碑,其1.x版本和2.x版本分别在不同的时期引领了MVC架构的设计与实现。以下是对Struts框架关键知识点的深度解析,涵盖Struts1.x的基础知识、配置过程、以及Struts标签的...
Struts2、Spring和Hibernate是Java企业级开发中常用的三个框架,它们构成了SSH(Struts2、Spring、Hibernate)框架体系,广泛应用于构建MVC(Model-View-Controller)架构的Web应用程序。Ajax(Asynchronous ...
Struts.2是Apache软件基金会下的一个开源项目,它是Struts 1.x的后续版本,继承了Struts 1.x的一些设计理念,但采用了更为先进的WebWork核心来实现MVC架构。相比于Struts 1.x,Struts.2具有更强大的功能和更高的灵活...
#### 二、Struts2与WebWork的关系 - **Struts2的核心**:基于WebWork框架的核心组件进行构建,继承了WebWork的优秀特性。 - **设计理念**:Struts2致力于提供更为简洁、灵活且易于使用的API,同时保持与Struts1.x的...
- **现代框架对比**:Struts 2与Spring MVC、Play Framework等现代框架相比,可能存在维护成本高、社区活跃度低等问题,开发者需要权衡选择。 总之,了解并掌握Struts的各个版本及其特性,对于理解Web开发的历史...
3. **Struts2与Spring整合**:`struts2-spring-plugin-2.3.4.jar`是整合插件,使得Action可以被Spring管理,实现依赖注入。 4. **其他辅助库**:如`antlr-2.7.2.jar`用于解析语言,`asm`系列库用于字节码操作,`...
例如,可能涉及Struts2的最新安全补丁、性能优化或者与Spring框架的深度集成。 通过阅读这些PDF文档,你可以深入理解Struts框架的核心概念,学习如何配置Action、配置文件、创建表单和结果映射,以及如何处理请求和...
- Spring 3.2.x 支持与各种框架的集成,如 MyBatis、Quartz、Struts 等,源码中可以看到这些集成的实现细节。 通过对 Spring Framework 3.2.x 源码的深入研究,我们可以更好地理解这个框架的工作原理,提高我们的...
《深入理解Struts 1.1及应用开发实例解析》则可能提供有关Struts 1.x实际应用的深度分析。《Struts标记库.doc》将详细介绍Struts 1中的JSP标签,帮助你更好地利用视图层。阅读这些文档,将有助于你成为一位熟练的...
### Struts Menu 学习指南:深度解析与实践 #### 引言 Struts Menu 插件是一款开源的菜单管理工具,专为简化基于Struts框架的Web应用中菜单配置和展示过程而设计。该插件的核心优势在于其简易的配置方式和高度的...
Struts2.0是Java Web开发领域中的一款流行框架,它是Struts1.x与WebWork框架的结合体,继承了两者的优点并进行了创新。在Struts2.0中,核心概念之一是Action,它被设计为一个简单的POJO(Plain Old Java Object),...
《精通Spring 2.x-企业应用开发详解》是Spring框架学习的经典著作,专注于Spring 2.x版本,这个版本在当时是广泛使用的。本章节聚焦于Spring在企业级应用开发中的深度应用,涵盖了许多关键概念和技术。以下是根据...
《精通Spring 2.x - 企业应用开发详解》是一本深度解析Spring框架2.x版本的专业书籍,涵盖了Spring在企业级应用中的核心技术和实践方法。在第18章和第19章中,作者深入探讨了Spring如何与相关技术如Hibernate、J2EE...
Struts 2可以与Spring框架深度集成,通过Spring管理Action实例,实现依赖注入(DI),提供事务管理,以及AOP功能。在配置中启用Spring插件,Action类就可以声明Spring Bean中的依赖,从而实现松耦合。 **标签库:**...
它继承了Struts1.x的优点并解决了其存在的问题。Struts2提供了拦截器机制,允许开发者定义和组织业务逻辑,增强了异常处理和国际化支持,还集成了Freemarker和Velocity等模板引擎,方便视图层的开发。 **Spring2.5*...