☆蓝色梦想☆

世界总是反反覆覆错错落落地飘去 来不及叹息 生活不是平平淡淡从从容容的东西 不能放弃
posts - 57, comments - 5, trackbacks - 0, articles - 0

Struts 应用转移到 Struts 2 (一)

Posted on 2007-03-04 00:51 ☆蓝色梦想☆ 阅读(338) 评论(0)  编辑  收藏 所属分类: Struct
翻译:SpringSide团队   转载请注明出处。

     有很多人都很熟悉 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中获取
    下图展示了整个请求的概要过程:


    整个请求过程可以分为六步骤:
    1. 一个请求产生并经由框架处理 - 框架根据请求匹配相应的配置,如使用哪些拦截器,action 类和结果。
    2. 请求通过一系列的拦截器 - 拦截器,和拦截器组经配置后,能处理不同等级的请求,它们为请求提供了各种预处理,切面处理。这和Struts的使用 Jakarta Commons Chain 构件的 RequestProcessor类很相似。
    3. 调用 Action - 产生一个新的action对象实例,并提供请求所调用的处理逻辑的方法。Struts2 可以在配置action时为请求分配其指定的方法。我们在第二部文章中将对这步骤进行进一步讨论;
    4. 调用产生的结果 - 获取通过action的方法处理后返回来的结果,匹配其result class并调用产生的实例。有种情况是在UI模板去生成HTML时才去处理这些结果。如果在这种情况下,在Struts2 模板中的tags能直接返回到 action 中,取结果来呈现界面。 
    5. 请求再次经过一系列的拦截器处理后返回 - 请求反顺序通过与原来进入时的拦截器链, 当然,你也可以配置在这个过程中减少或增加拦截器处理.
    6. 请求返回到用户 - 最后一步是由 control 返回到servlet。通常是生成HTML返回到user, 但你也可以指定返回的HTTP头或HTTP重定向。
      你应该已注意到,Struts2与Struts的差别。最明显的就是Struts2是pull-MVC 架构,就是可以直接从Action中获取所需要的数据,而不是像Struts那样必须把 beans 存到page, request,或者session中才能获取。这个我们将在下一章中详细提及。

      配置框架
      首先最重要的是,让框架能通过web.xml在servlet containers里运行。
      下面这个就是大家都熟悉的 Struts在 web.xml里的配置方法

         
      <servlet>
              <servlet-name>action</servlet-name>
              <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
              <init-param>
                  <param-name>config</param-name>
                  <param-value>/WEB-INF/struts-config.xml</param-value>
              </init-param>
              <load-on-startup>2</load-on-startup>
          </servlet>

          <servlet-mapping>
              <servlet-name>action</servlet-name>
              <url-pattern>*.do</url-pattern>
          </servlet-mapping>

      在 Struts2 中,这个有少许改变,最明显的是dispatcher 由servlet转为servlet filter, 其配置和servlet一样简单,如下:

         
       <filter>
               <filter-name>webwork</filter-name>
                 <filter-class>
                  org.apache.struts.action2.dispatcher.FilterDispatcher
         </filter-class>
          </filter>

          <filter-mapping>
         <filter-name>webwork</filter-name>
         <url-pattern>/*</url-pattern>
          </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 结构, 主要的形式如下:

      public class MyAction extends Action {
          public ActionForward execute(ActionMapping mapping,
                                       ActionForm form,
                                       HttpServletRequest request,
                                       HttpServletResponse response)
                  throws Exception {
              // do the work
              return (mapping.findForward("success"));
          }
      }

      当实现一个Struts action时, 你需要注意一下问题:
      1. 所有的action 都必须继承于base Action 类.
      2. 所有的action都必须是线程安全的,因为action是单例的,singleton的.
      3. 因为所有的action都必须是线程安全的,所以所有的对象都不能是类属性, 都必须以方法参数的形式传值。
      4. 调用action的方法必须命名为 "execute" ( 在Struts中的  DispatchAction 类好像可以用其它方法去执行同一个action ,但实际上在框架中调用的仍然是 "execute" 方法。).
      5. ActionForward 的结果是通过ActionMapping 类中的方法来产生的,通常是"findForward"方法.
        相比较之下, Struts2的action 提供了很多简单的实现。下面就是个例子

        public class MyAction {
           public String execute() throws Exception {
                // do the work
                return "success";
           }
        }

        首先你会注意到的是,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,如下

        public interface ServletRequestAware {
            public void setServletRequest(HttpServletRequest request);
        }

        当我们继承这个接口时,我们需要通过setter为我们的HttpServerRequest 属性变量赋值:

        public class MyAction implements ServletRequestAware {
           private HttpServletRequest request;
           public void setServletRequest(HttpServletRequest request) {
                this.request = request;
           }
           public String execute() throws Exception {
                // do the work using the request
                return Action.SUCCESS;
           }
        }

        看起来现在这些属性是类级别的,并不是线程安全的,但是在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/, cac 翻译)

        只有注册用户登录后才能发表评论。


        网站导航: