Blog信息 |
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7598369 建立时间:2006年5月29日 |

| |
[Struts 2.0]Struts 应用转移到 Struts 2 (一) 软件技术
lhwork 发表于 2006/11/30 13:36:11 |
有很多人都很熟悉 Struts, 无论是从项目中直接获得的实战经验还是从书中了解到的。我们这一系列文章,将通过一个由 Stuts 转移到 Struts2 简单的例子向大家展现Struts2的所有特征。
在我们开始这个例子之前,你需要去知道一点 Struts2的背景知识。
在第一部分的文章中,我们将介绍Struts2与Struts的核心框架的不同点,以助于更好地了解其他方面的整合。第二部分中,我们将深入探讨
actions 的差别, action相关的框架特征,和action配置。在最后一部分中,我们将会讲述 user
interface,我们也会讲到其架构,UI构件,themes 和标签。 还有如何为你的应用加上新的外观。 我们并不打算谈及迁移过程的所有细节方面,我们只是从出发点开始介绍Struts2 的概念和现在可用的所有特征。但拥有这些知识,你将在以后Struts2的应用中无往而不利。 Struts的历史
Struts的第一个版本 是在 2001年5月份发布。它提供了一个Web应用的解决方案,如何让 JSPs 和 servlets
共存去提供清晰的分离视图和业务和应用逻辑的架构。在Struts之前,最通常的做法是在JSP中加入业务和应用逻辑,或者在servlets中生成视
图。 自从第一个版本的发布, Struts
实际上已成为业界公认的Web应用标准。但随着时间的推移,Web应用框架经常变化的需求,产生了几个下一代
Struts的解决方案。其中两个可选方案是Shale 和 Struts Ti。 Shale 是一个基于构建的框架,并在最近成为 Apache
中的重要项目。而 Struts Ti 则是继续坚持 MVC模式的基础上改进,继续Struts的成功经验。
WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想,概念和功能,但和原Struts代码并不兼
容。WebWork是一个成熟的框架,经过了好几次重大的改进与发布。在2005年12月,WebWork与Struts Ti决定合拼, 再此同时,
Struts Ti 改名为 Struts Action Framework 2.0,成为Struts真正的下一代。请求如何运作 在我们开始详细探讨如何转移Struts到Struts2之前,让我们来看看整个请求流程在新架构中是如何运作的。你会注意到在整个请求的生命周期,仍是以controller作主体,而且所有的概念还都是你以前所熟悉的, 就如:通过URL请求的参数来调用Actions来把数据传给server. 所有的Servlet objects (request, response, session,之类.) 仍然可以在Action中获取 下图展示了整个请求的概要过程:500)this.width=500'>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.infoq.com/resource/articles/converting-struts-2-part1/en/resources/image1.jpg');}" alt="" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" src="http://www.infoq.com/resource/articles/converting-struts-2-part1/en/resources/image1.jpg" border="0">整个请求过程可以分为六步骤: 一个请求产生并经由框架处理 - 框架根据请求匹配相应的配置,如使用哪些拦截器,action 类和结果。 请求通过一系列的拦截器 - 拦截器,和拦截器组经配置后,能处理不同等级的请求,它们为请求提供了各种预处理,切面处理。这和Struts的使用 Jakarta Commons Chain 构件的 RequestProcessor类很相似。 调用 Action - 产生一个新的action对象实例,并提供请求所调用的处理逻辑的方法。Struts2 可以在配置action时为请求分配其指定的方法。我们在第二部文章中将对这步骤进行进一步讨论; 调用产生的结果 -
获取通过action的方法处理后返回来的结果,匹配其result
class并调用产生的实例。有种情况是在UI模板去生成HTML时才去处理这些结果。如果在这种情况下,在Struts2
模板中的tags能直接返回到 action 中,取结果来呈现界面。 请求再次经过一系列的拦截器处理后返回 - 请求反顺序通过与原来进入时的拦截器链, 当然,你也可以配置在这个过程中减少或增加拦截器处理. 请求返回到用户 - 最后一步是由 control 返回到servlet。通常是生成HTML返回到user, 但你也可以指定返回的HTTP头或HTTP重定向。
你应该已注意到,Struts2与Struts的差别。最明显的就是Struts2是pull-MVC
架构,就是可以直接从Action中获取所需要的数据,而不是像Struts那样必须把 beans 存到page,
request,或者session中才能获取。这个我们将在下一章中详细提及。配置框架首先最重要的是,让框架能通过web.xml在servlet containers里运行。下面这个就是大家都熟悉的 Struts在 web.xml里的配置方法 500)this.width=500'> <servlet>500)this.width=500'> <servlet-name>action</servlet-name>500)this.width=500'> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>500)this.width=500'> <init-param>500)this.width=500'> <param-name>config</param-name>500)this.width=500'> <param-value>/WEB-INF/struts-config.xml</param-value>500)this.width=500'> </init-param>500)this.width=500'> <load-on-startup>2</load-on-startup>500)this.width=500'> </servlet>500)this.width=500'>500)this.width=500'> <servlet-mapping>500)this.width=500'> <servlet-name>action</servlet-name>500)this.width=500'> <url-pattern>*.do</url-pattern>500)this.width=500'> </servlet-mapping> 在 Struts2 中,这个有少许改变,最明显的是dispatcher 由servlet转为servlet filter, 其配置和servlet一样简单,如下: 500)this.width=500'> <filter>500)this.width=500'> <filter-name>webwork</filter-name>500)this.width=500'> <filter-class>500)this.width=500'> org.apache.struts.action2.dispatcher.FilterDispatcher500)this.width=500'> </filter-class>500)this.width=500'> </filter>500)this.width=500'>500)this.width=500'> <filter-mapping>500)this.width=500'> <filter-name>webwork</filter-name>500)this.width=500'> <url-pattern>/*</url-pattern>500)this.width=500'> </filter-mapping> 和servlet配置一样,filter配置定义了名称(供关联)和filter的类。filter mapping让URI匹配成功的的请求调用该filter。默认情况下,扩展名为".action"。这个是在default.properties文件里的"struts.action.extension" 属性定义的。工具箱: "default.properties"是配置选项定义文件。通过在classpath中包含一个叫"struts.properties"的文件,并设置不同的属性值,你可以覆盖这个默认的配置,实现自己的配置。对于Struts, servlet配置提供了初始化tag的参数和使用的文件,而Struts2没有这样的配置参数,取而代之的是在classpath下的默认配置文件"struts.xml"。工具箱/提示:
Struts actions(扩展名".do"),Struts2
actions(扩展名".action"),所以Struts和Struts2可以在一个系统中共存。所以最好是保持原先的系统,在新功能的开发上用
Struts2, 如果时间和资源允许的情况下再逐步迁移。另一种方法是只是把Struts2的扩展名改为".do",可重用JSPs.分析Actions在上面介绍的请求运作流程中,我们谈及了一些Struts和Struts2的不同点。现在我们将较深入地探讨这两个框架中action结构的具体差别。让我们来回顾一下 Struts 的 action 结构, 主要的形式如下: 500)this.width=500'>500)this.width=500'>public class MyAction extends Action ...{500)this.width=500'> public ActionForward execute(ActionMapping mapping,500)this.width=500'> ActionForm form,500)this.width=500'> HttpServletRequest request,500)this.width=500'> HttpServletResponse response)500)this.width=500'>500)this.width=500'> throws Exception ...{500)this.width=500'> // do the work500)this.width=500'> return (mapping.findForward("success"));500)this.width=500'> }500)this.width=500'>} 当实现一个Struts action时, 你需要注意一下问题: 所有的action 都必须继承于base Action 类. 所有的action都必须是线程安全的,因为action是单例的,singleton的. 因为所有的action都必须是线程安全的,所以所有的对象都不能是类属性, 都必须以方法参数的形式传值。 调用action的方法必须命名为 "execute" ( 在Struts中的 DispatchAction 类好像可以用其它方法去执行同一个action ,但实际上在框架中调用的仍然是 "execute" 方法。). ActionForward 的结果是通过ActionMapping 类中的方法来产生的,通常是"findForward"方法. 相比较之下, Struts2的action 提供了很多简单的实现。下面就是个例子 500)this.width=500'>500)this.width=500'>public class MyAction ...{500)this.width=500'>500)this.width=500'> public String execute() throws Exception ...{500)this.width=500'> // do the work500)this.width=500'> return "success";500)this.width=500'> }500)this.width=500'>} 首
先你会注意到的是,Struts2中的action不再继承于任何类或需要实现任何接口。实际上,它还远不只这些。按照惯例,只有"execute"方法
能调用action, 但在Struts2中并非必要,任何声明为public String methodName()
方法都能通过配置来调用action.另外,你会注意到返回值不再是"ActionForward ",而是String,
如果你需喜欢String的形式,那在Action接口里有个帮助方法可以提供简单的结果常量,如"success", "none",
"error", "input" 和 "login"。最后,和Struts最大的革命性的不同是,
调用action不再是带参数的。那你如何在获得你所需要的值呢?答案是"inversion of control" 或 "dependency
injection", 反转控制(想了解更多可以看Martin Fowler的文章 http://www.martinfowler.com/articles/injection.html)。为了更好地了解反转控制,让我们来看看一个例子,如何在action处理过程中可以访问到HttpServerRequest 。在我们的例子中,我们用ServletRequestAware 接口,这个接口包含了相应属性的setter,如下 500)this.width=500'>500)this.width=500'>public interface ServletRequestAware ...{500)this.width=500'> public void setServletRequest(HttpServletRequest request);500)this.width=500'>} 当我们继承这个接口时,我们需要通过setter为我们的HttpServerRequest 属性变量赋值: 500)this.width=500'>500)this.width=500'>public class MyAction implements ServletRequestAware ...{500)this.width=500'> private HttpServletRequest request;500)this.width=500'>500)this.width=500'> public void setServletRequest(HttpServletRequest request) ...{500)this.width=500'> this.request = request;500)this.width=500'> }500)this.width=500'>500)this.width=500'> public String execute() throws Exception ...{500)this.width=500'> // do the work using the request500)this.width=500'> return Action.SUCCESS;500)this.width=500'> }500)this.width=500'>} 看起来现在这些属性是类级别的,并不是线程安全的,但是在Struts2里并没有问题,因为每个请求过来的时候都会产生一个新的action对象实例,它并没有和其他请求共享一个对象,所以不需要考虑线程安全问题。现在我们还有最后一步,就是把action关联上ServletConfigInterceptor 拦截器。这个拦截器继承了ServletRequestAware 接口,并提供了把HttpServletRequest 注入到action中的功能。但是你现在不用担心如何配置这些,我们将在下一篇文章中具体讲述。最重要的是我们明白了拦截器和接口共同为action提供了反转控制的功能。这
个设计的好处是能让action完全和框架解耦。action仅仅是一个被框架使用的简单的POJO。这对于单元测试但来极大的好处,
你能方便的为Struts action实现 StrutsTestCase 或 MockStrutsTestCase 单元测试。总结By到现在为止,你应该已经了解了Struts2的整个请求流程,还有高层的框架概念, 你也应该能自己动手配置Struts2的action,和讲出Struts和Struts2的差别了。在
下篇文章中,我们将会介绍一个详细的Struts应用向Struts2迁移的例子,同时我们也会介绍迁移中相关的知识,会讲述如何综合使用JSTL,
JSP 和
Struts2,进一步讲述Struts和Struts2的action的差别,Struts2的配置和其他框架元素,和谈到更多的其他相关框架的特征。(自http://www.infoq.com/) |
|
|