Struts 2.0相关知识 摘自Struts2权威指南(李刚 著)

 对于任何的MVC框架而言,其实只实现了C(控制器)部分,但它负责用控制器调用业务逻辑组件,并负责控制器与视图技

术(JSP,FreeMarker和Velocity等)的整合。

Struts 1框架与JSP/Servlet耦合非常紧密,从而导致了许多不可避免的缺陷:
  (1)支持的表现层技术单一
 Struts 1 只支持JSP作为表现层技术,这一点严重制约了Struts 1框架的使用。
 虽然 Struts 1处理完用户请求后,并没有直接转到特定的视图资源,而是返回一个ActionForward对象(可以理解ActionForward是一

个逻辑视图名),在struts-config.xml文件中定义了逻辑视图名和视图资源之间的对应关系,当ActionServlet得到处理器返回

的ActionForward对象后,可以根据逻辑视图名和视图资源之间的对应关系,将视图资源呈现给用户。
 从上面的设计来看,不得不佩服Struts 1的设计者高度解藕的设计:控制器并没有直接执行转发请求,而仅仅返回一个逻辑视图名---

实际的转发放在配置文件中进行管理。但是因为Struts 1框架出现的年代太早了,那个时候还没有FreeMarker,Velocity等技术,因而没有考虑

与FreeMarker,Velocity等视图技术的整合。

  (2)与Servlet API严重耦合,难于测试
 Struts 1完全是基于Servlet API的,所以在Struts 1的业务逻辑控制器内,充满了大量的Servlet API,当我们需要测试一个Action类

的execute方法时,该方法有4个参数:ActionMapping,ActionForm,HttpServletRequest和HttpServletResponse,初始化这4个参数比较困难,

尤其是HttpServletRequest和HttpServletResponse两个参数,通常由Web容器负责实例化。
 因为HttpServletRequest和HttpServletResponse两个参数是Servlet API,严重依赖于Web服务器,因此,一旦脱离了Web服务

器,Action的测试非常困难。
  (3)代码严重依赖于Struts API,属于侵入式设计
 Struts 1的Action类必须继承Struts 1的Action基类,实现处理方法时,又包含了大量Struts 1 API:如ActionMapping,ActionForm和

ActionForward类。这种侵入式设计的最大弱点在于,一旦系统需要重构时,这些Action类将完全没有利用价值,成为一堆废品。
 可见,Struts 1的Action类这种侵入式设计导致了较低的代码复用。


WebWork

 相对于Struts 1存在的那些先天性不足而言,WebWork则更加优秀,它采用了一种更加松耦合的设计,让系统的Action不再与Servlet

API耦合,使单元测试更加方便,允许系统从B/S结构向C/S结构转换。
 WebWork可以脱离Web应用使用,这一点似乎并没有太多优势,因为,一个应用通常开始已经确定在怎样的环境下使用。WebWork有自己

的控制反转容器,通过控制反转,可以让测试变得更简单,测试中设置实现服务接口的Mock对象完成测试,而不需要设置服务注册。
 WebWork 2使用OGNL这个强大的表达式语言,可以访问值栈,OGNL对集合和索引属性的支持非常强大。
 相对Struts 1的Action与Servlet API紧密耦合的弱点来说,WebWork的Action则完全与Servlet API分离,因而该Action更容易测试。
 WebWork的Action可以与Servlet API分离,得益于它灵巧的设计,它使用一个拦截器链,负责将用户请求数据转发到Action,并负责

将Action的处理结果转换成对用户的响应。
 当用户向Web应用发送请求时,该请求经过ActionContextCleanUp,SiteMesh等过滤器过滤,由WebWork的核心控制器拦截,如果用户请

求需要WebWork的业务逻辑控制器处理,该控制器则调用Action映射器,该映射器将用户请求转发到对应的业务逻辑控制器。值得注意的是,此

时的业务逻辑控制器并不是开发者实现的控制器,而是WebWork创建的控制器代理。
 创建控制器代理时,WebWork需要得到开发者定义的xwork.xml配置文件,控制器代理以用户实现的控制器作为目标,以拦截器链中的

拦截器作为处理(Advice).

WebWork中创建控制器代理的方式,就是一种AOP(面向切面编程)编程方式,只是这种AOP中的拦截器由系统提供,因此无需用户参与。

 开发者自己实现的业务逻辑控制器只是WebWork业务控制器的目标---这就是为什么开发者自己实现的Action可以与Servlet API分离的

原因。当开发者自己的Action处理完HTTP请求后,该结果只是一个普通字符串,该字符串将对应到指定的视图资源。指定的视图资源经过拦截

器链的处理后,生成对客户端的响应输出。
 
WebWork存在如下优点:
 (1)Action无需与Servlet API耦合,更容易测试
 在WebWork中的Action代码中,我们看不到任何的Servlet API,Action并未通过HttpServletRequest对象来获得请求参数,而是直接调

用访问该Action的成员属性---这些属性由Action拦截器负责初始化,以用户请求参数为其赋值。
 即使Action中需要访问Http Session对象,依然没有在代码中直接出现HttpSession API,而是以一个Map对象代表了Http Session对象

,如果需要测试Action代码,测试用例的书写将非常容易,因为execute方法中没有包含任何Servlet API,甚至没有WebWork的API.
 (2)Action无需与WebWork耦合,代码重用率高
 WebWork的Action其实就是一个POJO,该Action仅仅实现了WebWork的Action接口,包含了一个execute方法。
 Struts 1中的Action类需要继承Struts 1的Action类,我们知道,实现一个接口和继承一个类是完全不同的概念:实现一个接口对类

的污染要小得多,该类也可以实现其他任意接口,还可以继承一个父类;但一旦已经继承一个父类,则意味着该类不能再继承其他父类。而

且WebWork得execute方法中没有出现任何Servlet API,也没有出现任何WebWork API,这个方法在任何环境下都有重用的价值。
 (3)支持更多的表现层技术,有更好的适应性。

Struts 2起源:
 
 目前,Struts已经分化成两个框架:第一个框架就是传统Struts 1和WebWork结合后的Struts2框架,这个框架的核心采用的是WebWork
;Struts分化出来的另外一个框架是Shale,这个框架远远超出了Struts 1原有的设计思想,它与原有的Struts 1的关联很少,它使用全新的设

计思想。Shale更像一个新的框架,而不是Struts的升级。Shale在很多方面与Struts存在不同之处,其中有两点最为突出:
 . Struts 与JSF集成,而Shale则是建立在JSF之上。
 . Struts实质上是一个巨大的,复杂的请求处理器;而Shale则是一组能以任何方式进行组合的服务,简单地说,Shale是一种SOA(面

向服务架构)架构。


Struts 2体系介绍

 Struts 2的体系与Struts 1体系的差别非常大,因为Struts 2使用了WebWork的设计核心。Struts 2大量使用拦截器来处理用户请求,

从而允许用户的业务逻辑控制器与Servlet API分离。

 Struts 2同样使用拦截器作为处理(Advice).以用户的业务逻辑控制器为目标,创建一个控制器代理。
 控制器代理负责处理用户请求,处理用户请求时回调业务控制器的execute方法,该方法的返回值将决定了Struts 2将怎样的视图资源

呈现给用户。


Struts 2框架的大致处理流程如下:
   
    1. 浏览器发送请求,例如请求/mypage.action,/reports/myreport.pdf等。
   
    2. 核心控制器FilterDispatcher根据请求决定调用合适的Action.

    3. WebWork的拦截器链自动对请求应用通用功能,例如workflow,validation或文件上传等功能。
 
    4. 回调Action的execute方法,该execute方法先获取用户请求参数,然后执行某种数据库操作,既可以是将数据保存到数据库,也可以从

数据库检索信息。实际上,因为Action只是一个控制器,它会调用业务逻辑组件来处理用户的请求。
    5. Action的execute方法处理结果信息将被输出到浏览器中,可以是HTML叶面,图像,也可以是PDF文档或者其他文档。此时支持的视图技

术非常多,既支持JSP,也支持Velocity,FreeMarker等模板技术。


Struts 2的配置文件

 当Struts 2创建系统的Action代理时,需要使用Struts 2的配置文件。
 Struts 2的配置文件有两份:
    . 配置Action 的struts.xml文件。
    . 配置Struts 2全局属性的struts.properties文件。
 
 struts.xml文件内定义了Struts 2的系列Action,定义Action时,指定该Action的实现类,并定义该Action处理结果与视图资源之间

的映射关系。
 struts.xml配置文件的示例:
 <struts>
   <!-- Struts 2的Action 都必须配置在package里 -->
 <package name="default" extends="struts-default">
   <!-- 定义一个Logon 的Action实现类为lee.Logon -->
         <action name="Logon" class="lee.Logon">
    <!-- 配置Action返回input时转入ܹ/pages/Logon.jsp叶面 -->
              <result name="input">/pages/Logon.jsp</result>
    <!-- 配置Action返回cancel时重定向到Welcome 的Action-->
              <result  name="cancel"  type="redirect-action">Welcome</result>
    <!-- 配置Action返回success时重定向到MainMenu 的Action -->
              <result type="redirect-action">MainMenu</result>
    <!-- 配置Action返回expired时进入ܹChangePasswordⱘAction链 -->
              <result name="expired" type="chain">ChangePassword</result>
         </action>
   <!-- 定义一个Logoff的Action实现类为lee.Logoff -->
         <action name="Logoff" class=" lee.Logoff">
    <!-- 配置Action返回success时重定向到MainMenu 的Action -->
              <result type="redirect-action">Welcome</result>
         </action>
     </package>
 </struts>

 定义result元素时,可以指定两个属性:type和name 其中name指定了execute方法返回的字符串,而type指定转向的资源类型,此处

转向的资源可以是JSP,可以是FreeMarker等,甚至是另外的Action---这也是struts 2可以支持多种视图技术的原因。
  
 除此之外,Struts 2还有一个配置Struts 2全局属性的Properties文件:struts.properties。
 该文件的示例如下:

 #指定struts 2处于开发状态
 struts.devMode = false
 //指定当struts 2配置文件改变后,Web框架是否重新加载Struts 2配置文件
 struts.configuration.xml.reload=true
 
 正如上面见到的,struts.properties文件的形式是系列的key,value对,它指定了Struts 2应用的全局属性。
 


Struts 2的标签库
 
 Struts 2的标签库也是Struts 2的重要组成部分,Struts 2的标签库提供了非常丰富的功能,这些标签库不仅提供了表现层数据处理

,而且提供了基本的流程控制功能,还提供了国际化,Ajax支持等功能。
 
 Struts 2的标签库的功能非常复杂,该标签库几乎可以完全替代JSTL的标签库。而且Struts 2的标签支持表达式语言,这种表达式语

言支持一个强大和灵活的表达式语言:OGNL(Object Graph Notation Language),因此功能非常强大。


Struts 2的控制器组件

 Struts 2的控制器组件是Struts 2框架的核心,事实上,所有MVC框架都是以控制器组件为核心的。正如前面提到的,Struts 2的控制

器由两个部分组成:FilterDispatcher和业务控制器Action.

 实际上,Struts 2应用中起作用的业务控制器不是用户定义的Action,而是系统生成的Action代理,但该Action代理以用户定义

的Action为目标。
 
 Struts 2的Action比WebWork中的Action更彻底,该Action无需实现任何父接口,无需继承任何Struts 2基类,该Action类完全是一个

POJO,因此具有很好的复用性。
 
 归纳起来,该Action类有如下优势:
 . Action类完全是一个POJO,因此具有很好的代码复用性。
 . Action类无需与Servlet API耦合,因此进行单元测试非常简单。
 . Action类的execute方法仅返回一个字符串作为处理结果,该处理结果可映射到任何的视图,甚至是另一个Action.

Struts 2与Struts 1的对比

 . 在Action实现类方面的对比:Struts 1要求Action类继承一个抽象基类;Struts 1的一个具体问题是使用抽象类编程而不是接

口。Struts 2Action类可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务成为可能。Struts 2提供一个ActionSupport基类

去实现常用的接口。即使Action接口不是必须实现的,只有一个包含execute方法的PoJO类都可以用作Struts 2的Action.

 . 在线程模式方面的对比:Struts 1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例

策略限制了Struts 1 Action能做的事,并且要在开发时特别小心。Action资源必须是线程安全的或者同步的;Struts 2 Action对象为每一个

请求产生一个实例,因此没有线程安全问题。
 
 .Servlet依赖方面的对比:Struts 1 Action 依赖于Servlet API,因为Struts 1 Action的execute方法中

有HttpServletRequest和HTTPServletResponse方法。Struts 2 Action不再依赖于Servlet API,从而允许Action脱离Web容器运行,从而降低了

测试Action的难度。当然,如果Action需要直接访问HTTPServletRequest和HttpServletResponse参数,Struts 2 Action 依然可以访问他们。

但是大部分时候,Action都无需直接访问HttpServletRequest和HttpServletResponse,从而给开发者更多灵活的选择。

 .可测性方面的对比:测试Struts 1 Action的一个主要问题是execute方法依赖于Servlet API ,这使得Action的测试要依赖于Web 容

器。为了脱离Web容器测试Struts 1的Action,必须借助于第三方扩展:Struts TestCase,该扩展下包含了系列的Mock对象(模拟

了HttpServletRequest和HttpServletResponse对象),从而可以脱离Web容器测试Struts 1 的Action类。Struts 2 Action可以通过初始化,属

性设置,调用方法来测试。

 .封装请求参数的对比:Struts 1使用ActionForm对象封装用户的请求参数,所有的ActionForm必须继承一个基类:ActionForm。普通

的JavaBean不能作用ActionForm,因此开发者必须创建大量的ActionForm类封装用户请求参数。虽然Struts 1 提供了动态ActionForm来简

化ActionForm的开发,单依然需要在配置文件中定义ActionForm;Struts 2直接使用Action属性来封装用户请求属性,避免了开发者需要大量开

发ActionForm类的繁琐,实际上,这些属性还可以是包含子属性的Rich对象类型。如果开发者依然怀念Struts 1 ActionForm的模式,Struts 2

提供了ModelDriven模式,可以让开发者使用单独的Model对象来封装用户请求参数,但该Model对象无需继承任何Struts 2基类,是一个POJO,

从而降低了代码污染。

 . 表达式语言方面的对比:Struts 1整合了JSTL,因此可以使用JSTL表达式语言。这种表达式语言有基本对象图遍历,但是在对集合

和索引属性的支持上则功能不强;Struts 2可以使用JSTL,但他整合了一种更强大和灵活的表达式语言:OGNL,因此,Struts 2下的表达式语言

功能更加强大。
 
 . 绑定值到视图的对比:Struts 1使用标准JSP机制把对象绑定到视图叶面;Struts 2使用"ValueStack"技术,使标签库能够访问值,

而不需要把对象和视图叶面绑定在一起。

 . 类型转换的对比:Struts 1 的ActionForm属性通常都是String 类型。Struts 1使用Commons-Beanutils进行类型转换,每个类一个

转换器,转换器是不可以配置的;Struts 2使用OGNL进行类型转换,支持基本数据类型和常用对象之间的转换。

 . 数据校验的对比:Struts 1支持在ActionForm重写validate方法中手动校验,后者通过整合Commons validator框架来完成数据校验

。Struts 2支持通过重写validate方法进行校验,也支持整合XWork校验框架进行校验。

 . Action执行控制的对比:Struts 1支持每一个模块对应一个请求处理(即生命周期的概念),但是模块中的所有Action必须共享相同

的生命周期。struts 2支持通过拦截器堆栈(Interceptor Stacks) 为每一个Action创建不同的生命周期。开发者可以根据需要创建相应堆栈,

从而和不同的Action一起使用。

 

WebWork 和Struts 2对比
 
 在很多方面,Struts 2仅仅是改变了WebWork下的名称.

 Struts 2也删除了WebWork中少量特性:
     . AroundInterceptor :Struts 2不再支持WebWork中的AroundInterceptor。如果应用程序中需要使用AroundInterceptor,则应该自己手动导入WebWork中的AroundInterceptor类。

     . 富文本编辑器标签 :Struts 2不再支持WebWork的富文本编辑器,如果应用中需要使用富文本编辑器,则应该使用Dojo的富文本编辑器。
     . IoC容器支持 :Struts 2不再支持内建的IoC容器,而改为全面支持Spring的IoC容器,以Spring的IoC容器作为默认的Object工厂。
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值