`
toxy
  • 浏览: 71404 次
  • 性别: Icon_minigender_1
  • 来自: 云南.昆明
社区版块
存档分类
最新评论

Struts应用转移到Struts 2 ( 二 )

阅读更多
   在Struts2中,可选的实现方式有很多,可以像Struts那样每个需求用例对应一个action,也可以用一个action对应所有需求用例。但在我们的例子中,使用的方法是我认为最佳的解决方案 - 在一个action类中实现整套CRUD功能。
     也许你人为把list需求用例也同样地整合到同一个action类里会比较好,而我认为把list的功能分到另外一个action中,会减少容易产生的混淆,因为list用例中并不需要Blog这个类作为属性,而在其他用例中则需要。
    Struts2可以分别实现ServletRequestAware 接口,Prepareable 接口和 ModelDriven 接口。
     首先回顾一下ServletRequestAware, 我们在第一篇文章中已经详细介绍它了。这个ParametersInterceptor 拦截器提供了把HttpServletRequest 自动set到action中的功能,让我们能通过request, 把所需的值传回到JSPs。
     接着看看Preparable 接口, 它会联合PrepareInterceptor拦截器一起工作,让action在执行execute() 方法前, 执行一个prepare()方法,实现在执行前设定,配置或预设一些值在action中。 在我们的例子里,prepare方法会检查blogId 属性,如果为零则这是一个新日志,非零则该日志已经存在,根据blogId取出日志。
     最后我们说说ModelDriven 接口,在上一篇文章中,我们已经了解到 Struts action的很大的不同在于它是需要线程安全的,而在Struts2中则没有这个限制,因为每次的请求都会有一次action对象的初始化和调用。没有了这个限制,能允许Struts2使用类级别的属性变量(特别是getters和setters),从而获得更多编码优势。
    和拦截器的功能结合起来, 把HttpServletRequest 中的attribute 注入action中的流程如下所示:
    (1)循环读取HTTP request中的attribute
    (2)查找当前request attribute中是否有和action中的setter中的属性匹配的   (3)有则根据attribute从HttpServletRequest 里取出其值
     (4)把取出来的值由String转成setter中相应的类型
     (5)调用setter把该转换后的值注入action中

  提示: 当调用action时,如果发现不明原因使不能正确地通过setter注入值情况下,第一步最好是先检查下各拦截器,确保它们都已作用于该action。因为这些意外通常有时由拦截器设置不当形成的,检查是否各个拦截器都已起作用,并看看它们作用的顺序,因为有些情况下它们间会相互影响而产生错误。

    现在我们已经有基于String类型的form bean中取值的方法或者是自动把request的attributes 注入到action的方法,那下一步就是如何把值传入 domain object 或 value / transfer object的属性中去。其实这很简单,你只需要实现ModelDriven 接口(即实现getModel()方法)就可以了,确保ModelDrivenInterceptor 拦截器已作用于action。
    除了会调用action中的setter外,model 首先检查是否有和setter可以匹配当前的attribute名。如果在model中没有这个attribute相应的setter,则会再在action上找相应的setter来设值。
    在BlogAction 的例子中我们可以看到如何很灵活地使用这些方法,首先通过prepare() 方法根据Id获取相应的 Blog model object 或新建一个instance, 然后再根据把request中相应的属性注入Blog instance中和action中。
    以上的两个功能使得现在调用action那么简单 - 调用具体的业务逻辑,和把数据设在HttpServletRequest供返回用。

    public class BlogAction extends ActionSupport
         implements ModelDriven, Preparable, ServletRequestAware {

     private int blogId;
     private Blog blog;
     private BlogService service = new BlogService();
     private HttpServletRequest request;

     public void setServletRequest(HttpServletRequest httpServletRequest) {
         this.request = httpServletRequest;
     }

      public void setId(int blogId) {
         this.blogId = blogId;
     }

      public void prepare() throws Exception {
         if( blogId==0 ) {
             blog = new Blog();
         } else {
             blog = service.findById(blogId);
         }
     }

      public Object getModel() {
         return blog;
     }

      public String save() {
         service.create(blog);
         return SUCCESS;
     }
      public String update() {
         service.update(blog);
         request.setAttribute("blog",blog);
         return SUCCESS;
     }

      public String remove() {
         service.delete(blogId);
         return SUCCESS;
     }

      public String execute() {
         request.setAttribute("blog",blog);
         return SUCCESS;
     }
}


  配置Action:

   在我们调用action之前,我们必须通过XML配置文件去配置它们。
    在Struts中, 我们习惯用在WEB-INF 目录的"struts-config.xml"配置文件,在这里我们需要配置action form和action属性。在Struts2中, 用的是在classpath中的"struts.xml"配置文件, 它看起来好象会稍微复杂一些,因为它需要在配置action的同时也配置其拦截器。
   在我们的例子中,配置Struts的Action和配置Struts2的Action有三点不同:

<一>重定向配置
    在Struts的配置中,每个mapping 都需要提供调用action时所需要对应的路径,Struts默认为".do", 例如paht是"/struts/add"对应于URL"/struts/add.do"。同时也需要一个forward 属性来提供给URL去转向,如"/struts/add.jsp"。
    <struts-config>
     ...

      <action-mappings>

          <action path="/struts/add" forward="/struts/add.jsp"/>
         ...

      </action-mappings>
</struts-config>

   而Struts2的需要更多的一些配置,如:
   <struts>
      <include file="struts-default.xml"/>

      <package name="struts2" extends="struts-default" namespace="/struts2">

          <action name="add" >
             <result>/struts2/add.jsp</result>
         </action>
         ...

      </package>
  </struts>
   首先你会注意到的是,代替action-mappings 节点的是include 和package 节点。Struts2可以把配置细分到任意数目的配置文件中,来实现配置可模块化管理。每个配置文件的结构其实都是一样的,不同的只是文件名。
    include 节点中,以文件名作为file 属性,可把所include的文件内容包含到当前文件中。
   package 节点把actions组成一组,其name 属性的值必须是唯一的。
   在 Struts action的配置中, paht属性需要指定完整的URL路径。而在Struts2中,URL是通过package节点中的namespace属性,还有在action 节点中的name 属性, 和action扩展(默认是".action")共同起作用的。在上面的例子中,则URL为"/struts2/add.action"时会调用action。
   package节点除了可以分离命名空间外, package 节点中的 extends 属性,还提供了某种可复合的组成结构。通过继承另外一个package节点,你就能继承那个节点的配置,包括其actions, results, interceptors, exception,等值。在我们的例子中,"struts2" package节点继承了 "struts-default" package 节点(在"struts-default.xml" 文件里定义了该节点) ,注意这个是主要的include文件,所以必须在所有配置之前的第一行中写出。 这个功能有助于大大减少你重复性输入默认配置所浪费的时间。
    最后是result 节点, 它只是存放你这个action所需要转向的URL. 在这里我们没有提及name 和 type 属性。如果你不想改变它们的默认属性的话,你能忽略不写它们,让你的配置文件看起来更清晰。从action返回的 "success" 的结果将组成这个JSP显示给用户。


<二>Action配置
    在Struts 中forward 节点指定了action处理后,结果将重定向到哪个相应的页面。type属性指定了action的类,scope 属性保证了form beans只在request范围内。
    <struts-config>
     ...

      <action-mappings>

          <action path="/struts/list" scope="request"
                 type="com.fdar.articles.infoq.conversion.struts.ListBlogsAction" >
             <forward name="success" path="/struts/list.jsp"/>
         </action>
         ...

      </action-mappings>
  </struts-config>
   Struts2 的 XML配置和上面提到的基本相同。唯一不同的就是通过class属性为action节点提供了它所需要调用的类的完整路径。
    <struts>
     ...

      <package name="struts2" extends="struts-default" namespace="/struts2">

          <default-interceptor-ref name="defaultStack"/>

          <action name="list"
                 class="com.fdar.articles.infoq.conversion.struts2.ListBlogsAction">
             <result>/struts2/list.jsp</result>
             <interceptor-ref name="basicStack"/>
         </action>
         ...

      </package>
</struts>

    如果是用其他的方法而不是用默认的execute 方法去调用action(在BlogAction 类中大多数方法如此), 则需要在action节点的 method 属性里加入方法名,下面就是个例子,这时候update方法将会被调用。
    <action name="update" method="update"
    class="com.fdar.articles.infoq.conversion.struts2.BlogAction" >
        ...
    </action>

   default-interceptor-ref 和 interceptor-ref 节点有几点不同。在第一篇文章中,我们看到在action被调用之前必须通过一系列的拦截器,而这两个节点就是用来配置拦截器组的。default-interceptor-ref 节点为该package提供了默认的拦截器组。当在action节点中提供 interceptor-ref节点时 ,它就会覆盖默认的拦截器(interceptor-ref 节点能够和单独一个拦截器相关联,或者跟一个拦截器组相关联),在action节点中可以存在多个interceptor-ref节点,处理拦截器组的顺序会和该节点列出的顺序一致。

<三> 再重定向配置
    当我们提交表格的时候,我们需要重定向到更新后的结果页面。这个通常称为 "post-redirect pattern" 或, 最近出现的, "flash scope."
    由于这是一个form, 所以在Struts中我们需要为Struts指定一个ActionForm。需要在name属性中提供form的名称,同样地,我们也需要在forward 节点中举加入redirect属性为true。
    <struts-config>
     ...

      <action-mappings>
          <action path="/struts/save"
                 type="com.fdar.articles.infoq.conversion.struts.SaveBlogEntryAction"
                 name="blogForm" scope="request">
             <forward name="success" redirect="true" path="/struts/list.do"/>
          </action>
         ...

      </action-mappings>
</struts-config>

   Struts2 在result 节点里提供了type 属性, 默认情况下是"dispatch", 如果需要重定向,则需要设为 "redirect"。
   <struts>
     ...

      <package name="struts2" extends="struts-default" namespace="/struts2">

          <action name="save" method="save"
                 class="com.fdar.articles.infoq.conversion.struts2.BlogAction" >
             <result type="redirect">list.action</result>
             <interceptor-ref name="defaultStack"/>
          </action>
         ...

      </package>
</struts>
 
总结

    我们并不可能在这篇文章中覆盖所有的内容,如果你需要更好的了解整个框架,还有其他的实现方式和选项,这里有几点可以供你参考:
    配置拦截器和拦截器组 - 以Struts2-core JAR 包里的"struts-default.xml" 文件作为例子。"struts-default.xml" 演示了如何配置你自己的拦截器组,包含新的拦截器,你可以尝试实现自己的拦截器。
    配置文件中的通配符模式 - 你可以选择使用Struts2中的通配符模式来简化你的配置。
    通过 ParameterAware 接口把form值传入maps中 - 你可以在Struct2中配置,让所有request的form属性都存于action的一个map中,这样就不需要专门再为action指定model / transfer / value object了。这和Struts的dynamic form特点很相似。
    也许到现在为,也许你有个疑问,"迁移后我们的界面是否可以完全重用呢?",答案是yes。你能从这里, 下载到我这篇文章中的完整源代码,你可以自己尝试把URL的扩展名由".do" 改为 ".action",使用的页面时一样的。除此之外,其实用JSTL来代替Struts taglib也是很容易的。

                      (自 http://www.infoq.com , cac 翻译)
 



分享到:
评论
1 楼 modun 2008-08-22  
谢谢,受教了!!

相关推荐

    从Struts应用开发框架转移到Struts 2 WEB框架 教程

    从Struts应用开发框架转移到Struts 2 WEB框架 教程

    Struts2 in action中文版

    8.1.1 页面上:如何使用自定义结果组件构建Struts 2 Ajax应用程序 171 8.1.2 实现JSON结果类型 173 8.2 常用的结果类型 180 8.2.1 RequestDispatcher,也叫做dispatcher 180 8.2.2 ServletRedirectResult,也叫做...

    struts2 标签库 帮助文档

    struts2框架的标签库分为三类: 用户标签:生成HTML元素 非用户标签:数据访问、逻辑控制等。 AJAX标签:支持AJAX技术。 用户界面标签又分两类: 表单标签:生成HTML页面的from元素 非表单标签:生成页面上的...

    structs程序设计从入门到精通word文档

    1.5 你的第一个struts应用程序 8 第2章深入Struts结构 8 2.1人介绍应用框架 mvc和model2 8 2.2 Struts原理、开发及项目实施 8 2.3使用STRUST控制流 8 2.4讨论STRUTS的优缺点 9 2.5 Struts入门经验 9 2.6用strtus制作...

    Struts in Action中文版

    2. 深入 STRUTS架构..................................................................................37 2.1. 随便谈谈......................................................................................

    Struts + Spring + Hibernate整合开发

    Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发. IOC 控制反转 PersonDaoBean 是在...这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。

    struts in Action

    2. 深入STRUTS 架构..................................................................................37 2.1. 随便谈谈.......................................................................................

    外文翻译 stus MVC

    Struts is a set of cooperating classes, servlets, and JSP tags that make up a reusable MVC 2 design. This definition implies that Struts is a framework, rather than a library, but Struts also contains...

    Spring面试题

    IOC 将处理事情的责任从应用程序代码转移到框架。正如我将在下一个示例中演示的那样,Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。 BeanFactory 接口 因为 org.springframework.beans....

    超级有影响力霸气的Java面试题大全文档

    抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承:  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

    Spring 2.0的 'spring-jmx.jar' 和 'spring-remoting.jar'已经被转移到 Spring 2.5的'spring-context.jar' (针对 JMX 和非HTTP 远程支持),部分转移到 'spring-web.jar' (针对HTTP 远程支持)。 Spring 2.0的 '...

    ssh(structs,spring,hibernate)框架中的上传下载

     以上是Spring+Hibernate将文件二进制数据持久化到数据库的解决方案,而Struts通过将表单中file类型的组件映射为ActionForm中类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。  工程...

    Spring基础与快速入门

    Spring作为实现J2EE的一个全方位应用程序框架,为我们开发企业级应用提供了一个健壮、高效的解决方案。所谓全方位,不得不说以下几个特点: 1 非侵入式:对于写代码从来不考虑复用和移植的程序员来说,这一点根本...

    Maven2 的新特性.7z

    POM是Maven的核心对象模型,在Maven2中POM已由project.xml转移到pom.xml中使用,版本也由3升级为4。对于项目,一般只需要pom.xml就行了。 在Maven2中不需要也不提倡使用maven.xml,原因如下: • plugin的易用性的...

    DevOps-Cloud:DevOps是一种软件工程文化,它将软件开发人员和软件操作员系统管理员召集在一起

    持续集成:轻松地在开发,运营和支持领域之间转移知识和经验。 持续部署:快速持续发布新版本的软件或服务。 持续反馈:来自软件或服务生命周期各个阶段的团队的频繁反馈。 DevOps路线图 配置CI / CD 快速开始

    java 面试题 总结

    抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类...

Global site tag (gtag.js) - Google Analytics