Struts 2介绍
WebWork(http://www.opensymphony.com/webwork/)是一个历史很悠久的优秀的Web层开发框架。根据一些资料我们了解到,WebWork 1 和Struts 1是很接近的设计思路,比较
紧耦合,这体现在它的控制器类必须继承自某些特定的类或者接口,需要单独的传值对象:
FormBean,开发人员需要直接操纵request,response和session这些对象,页面的转向需
要通过特殊的对象来完成(ActionForward)。然而WebWork 2之后,它大胆引入了插件机
制,拦截器,依赖注入,以及POJO的开发模式,并对开发人员屏蔽底层的request, response
等对象,页面的转向通过返回String类型即可完成,便于单元测试,并抛弃了一代中的表单
Bean,让表单参数获取和Action对象合二为一,从而和JSF一道处于第二代Web框架的级别上(很遗憾的是Spring MVC到现在为止也还是停留在Struts 1 的模式上,除了IOC和Spring紧密集成之外,无其它特色,这也是它为何至今未被人视为优秀的Web开发框架的原因之一)。WebWork 2花了很大功夫来简化程序员负担,首先就是框架尽量避免让开发人员来在配置文件中编写不必要的内容,另外拦截器和IOC的配套使用,也大大简化了传统的一些任务例如文件上传。对于常见的动辄N兆的一堆库文件的不知该如何取舍的Web层框架来说,WebWork 2 的插件机制可以让你在核心类库的基础上按需装配,根据项目的需要来自由增删类库文件(这是和Spring内核差不多的做法吧)。那么第三代Web层框架,目前来说尚未出现,据说尚未推出的JSF的 2.0 版本将会支持号称无配置文件,纯标注(Annotation),POJO的开发模式,是否这就是第三代Web开发框架?根据文档,我发现Struts 2 也正在进行无配置文件+标注版本的开发工作,看来这的确是个趋势啊。纵观现有框架,配置文件繁琐,要想用框架,必先XML+自定义标签库的确是个让人一直头疼不已的老毛病了(让人想起来了东方不败的那句欲练神功,挥剑自X) ,一个框架一套配置文件和标签库,的确是让开发人员苦不堪言。笔者从心底里希望Java的Web层框架能易用化,标准化(大家都用一样的接口和标签库) ,开发工具智能化(微软Visual Studio .NET 那真不是盖的),开发人员傻瓜化……不过这样一来工资是不是也下降,我可就不知道了。
后来 Struts和 WebWork 进行合并,大家一起聚集在 Apache基金会这棵大树下,借着
Struts 这个响当当的硬牌子,推出了 Struts 2 框架,大家不要误会,它仍然也是基于 MVC
模式的开发框架,所有 WebWork 2 的优点它这里也有。据一些文档的说法认为 Struts 2 就
是 WebWork 的部分包重命名,配置文件稍作改动得来的,经过检验目前来看也的确如此。
不过因为 Struts 1 和 WebWork 2 仍然有大量开发人员喜欢使用,所以并未消失,仍然在各
自的支持者下继续发展着。除了传统的例如流程跳转,国际化消息等等之外,Struts 2 还支
持 AJAX 等的开发(目前是基于 DOJO 框架的实现),多种表示层框架(不仅仅局限于 JSP
页面展示),以及插件机制,已经发展成了一个全面的 Web 层框架。
注意:Struts 2 和 Struts 1的代码并不兼容,包括包文件和配置文件都不一样,Struts 1
的程序必须加以修改才能运行于 Struts 2之下,可以认为它们是两个不同的框架!
以下是其官方网站的特性介绍:
• 开发!
o 容易上手 – 从教程和模版程序或者 Maven 原型可以很容易的开发出新项目。
o 改进的设计 – 清晰的代码设计对应着独立于 HTTP 的框架接口。
o 增强的标签(Tag) - 使用样式表驱动的表单标签以及所提供的标签可以减少编码量。
o 有状态的复选框(Checkbox) - 避免了特殊的处理代码,职能复选框能感知自己的状态何时被切换。
o 灵活的取消按钮 – 取消时直接转向另一个操作(action)。
o 最好的AJAX 支持 – 通过使用和标准Struts标签观感一致的 AJAX 标签,可以增加交互性和灵活性。
o 方便的 Spring 集成 – 使用 Spring 向 Action 中注入依赖关系,无需编写
额外的连接代码或者其它配置 。(同时支持 Plexus?)
o 增强的表示层展示 – 可以将处理结果以 JasperReports, JFreeChart,
Action 链, 或者文件下载的方式展示。
o POJO 表单 – 不需要 ActionForm! 可以使用任何 JavaBean 来捕获输入
或者直接将属性设置到 Action 类上。可以同时使用二进制和字符串类型的
属性!
o POJO Action – 使用任何类作为 Action 类 – 甚至接口也是可选的!
• 发布!
o 方便的插件机制 – 添加JAR文件即可添加框架扩展。无需人工配置!捆绑
的插件提供对 JavaServer Faces, JasperReports, JFreeChart, Tiles... ...等
众多框架的支持。
o 内置调优 – 查看Struts2 内部,找到死循环的位置!
o 准确的错误汇报 – 直接跳转到错误的位置和行号。
• 维护!
o 便于测试的Action – 可以直接测试Struts2 Action,无虚依赖任何模拟的HTTP 对象。
o 聪明的默认值 – 跳过明显的或者多余的设置。大多数框架的配置元素都有默认值可以使用,我们可以忘记它。只需要配置一次!
o 容易自定义的控制器 – 需要时可以自定义每个Action的请求处理。Struts2可以用你需要的方式来工作!
o 内置调试 – 使用内置调试器可以生成问题报告。
o 易于调整的标签 – 修改 FreeMarker 模版即可自定义标签。不需要再学习
taglib API! 完全支持 JSP, FreeMarker, 以及 Velocity 标签。
Struts 2 框架采用的许可是Apache License, Version 2.0,可以通过访问这个地址阅读:
http://www.apache.org/licenses/LICENSE-2.0。当然是可以免费用于我们自己的商业软件
的。它的标志图(Logo)如下所示:
运行 Struts 2 需要下列的条件:Servlet API 2.4,JSP API 2.0,Java 5(或者使用 j4
版本,运行于 JDK1.4)。当然换句话说用 Tomcat 5 或者更高版本就没有任何问题了。
Struts 2 的执行流程大致如此所示:Web 服务器启动解析 struts.xml,初始化消息文件,
Action 路径映射等资源,初始化框架→用户请求 XXX.action →Struts 2 过滤器使用对象工
厂(Object Factory,可以是自带或者是 Spring)创建 Action 类的示例 →执行 IOC和拦截器
(包括解析表单参数,文件上传,将解析结果注入 Action 对象) →调用 Action 中用户编
写的业务方法 →根据返回的结果(Result)路径转向视图层 →视图层进行显示(包括调用标
签库等)。
关于其底层结构,从网上搜集到的一些资料认为:WebWork 2,实际上是 Webwork +
XWork 的总集,Webwork1.x 版本中,整个框架采用了紧耦合的设计(类似 Struts 1.x),
而 WebWork 2.0 之后,Webwork 被拆分为两个部分,即 Webwork 2.x +XWork 2.x。当
一个请求发起后,从请求的路径名中解析出对应的 Action 名称,然后 Webwork 2.x框架会
遍历 HttpServletRequest、HttpSession、ServletContext 中的数据,并将其复制到内部的
Map 实现中,至此之后,所有数据操作均在此 Map 结构中进行,从而将内部数据结构与
Servlet API 相分离。至此,Webwork 的工作阶段结束,数据将传递给 XWork 进行下一步
处理。从这里也可以看到 Webwork 和 XWork 之间的切分点,Webwork 为 XWork 提供
了一个面向 Servlet 的协议转换器,将 Servlet 相关的数据转构转换成 XWork 所需要的通
用数据格式,而 XWork将完成实际的服务调度和功能实现。这样一来,以 XWork 为核心,
只需替换外围的协议转换组件,即可实现不同技术平台之间的切换。那么 Struts 2 呢,就是这样一个 Struts 2核心平台+XWork 的实现,其中的 XWork 部分执行和 Servlet API 无关的流程处理,而 Struts 2的核心层则提供将 Servlet 层提供的数据进行独立封装的过程,进而XWork 基于这些数据进行操作,这样就实现了一个完整的开发框架。XWork 相当于一个插件一样和现有框架组合,构成一个完整的流程处理+Servlet 操纵框架。所以大家会奇怪的看到 Struts 2 一共有两个核心 jar 文件:struts2-core-2.0.11.jar 和 xwork-2.0.4.jar,而且更让人奇怪的是前一个文件中的包定义是 org.apache.struts2,而后一个文件中的则是
com.opensymphony.xwork2,其原因就在于此。本段所介绍的内容仅供提供更多信息之用,
笔者不保证任何准确性和有效性。☺
为了便于读者了解相关内容,我把搜集到的一篇关于 Struts1 和 2 的短文列在这里(来
源见本章结尾参考资料):
特性比较:
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一起使用。
但是比较遗憾的是,目前 MyEclipse 6对 Struts 2 的开发还没有提供任何直接的支持,
所以本章我们将不得不手工加入相关的 jar 文件来开发,不过您会发现相比较 Struts 1 来说,其开发过程要简单的多。