其他分享
首页 > 其他分享> > Struts1与Struts2的区别和对比

Struts1与Struts2的区别和对比

作者:互联网

本文介绍了Struts2的起源,详细对比了Struts2和Struts1.x的差异,并穿插概述了Struts2框架及其请求流程。

本文介绍了两者在Action方面、对 Servlet 的依赖方面、输入捕获方面和表达式语言等十几个方面的差别,同时指出了Struts2对拦截器与IOC的支持,而在Struts1.x中这些特性是很难想象的。

前言

Struts 的第一个版本是在2001年5月份发布的。它的最初设想是: 通过结合JSP和Servlet,使Web应用的视图和业务/应用逻辑得以清晰地分离开来。

在Struts之前,最常见的做法是在JSP中加入业务和应用逻辑,或者在Servlet中通过 println() 来生成视图。

自从第一版发布以来,Struts实际上已成为业界公认的Web应用标准。它的炙手可热也为自己带来了改进和变更,其不但要跟上Web应用框架不断变化的需求,而且要与日渐增多竞争激烈的众多框架的特性相融合。到最后,产生了几个下一代Struts的解决方案,其中两个最受瞩目的方案是 ShaleStruts Ti

Shale Framework

Shale是一个基于构件的框架,并在成为Apache的顶级项目;而Struts Ti则是在Struts的成功经验基础上继续坚持对前端控制器(Front Controller) 和 MVC(model-view-controller)模式进行改进。

WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想、概念和功能,但和原Struts代码并不兼容。

WebWork是一个成熟的框架,经过了好几次重大的改进与发布。在2005年12月,WebWork与Struts Ti宣布合并。

与此同时,Struts Ti改名为Struts Action Framework 2.0,成为Struts真正的继承者。需要特别注意的是,全新的Struts2的体系结构与Struts1差别巨大,因为Struts2是以WebWork为核心的,继承了更多的WebWork血统,并吸收了struts1和webwork的优势。

需要指出的是,由于人们对这两个项目的兴趣仍然很高,而且也有很多开发者仍然愿意使用它们,因此这两个项目还在继续开发中,继续修复Bug,改进功能和继续添加新功能。

接下来,就让我们来详细了解一下Struts2与Struts 1.x的差异吧!

Action 方面

Action的区别

对于有着丰富的Struts1.x开发经验的朋友来说,都十分的清楚Action是整个Struts框架的核心内容,当然Struts2也不例外。

不过,Struts1.x与Struts2的Action模型很大的区别。

最后,我们分别看一下 Struts 1.3.10 和 Struts2.5.30 对Action官方注释:

Struts1.3.10

/**
 * <p>An <strong>Action</strong> is an adapter between the contents of an
 * incoming HTTP request and the corresponding business logic that should be
 * executed to process this request. The controller (RequestProcessor) will
 * select an appropriate Action for each request, create an instance (if
 * necessary), and call the <code>execute</code> method.</p>
 *
 * <p>Actions must be programmed in a thread-safe manner, because the
 * controller will share the same instance for multiple simultaneous requests.
 * This means you should design with the following items in mind: </p>
 *
 * <ul>
 *
 * <li>Instance and static variables MUST NOT be used to store information
 * related to the state of a particular request. They MAY be used to share
 * global resources across requests for the same action.</li>
 *
 * <li>Access to other resources (JavaBeans, session variables, etc.) MUST be
 * synchronized if those resources require protection. (Generally, however,
 * resource classes should be designed to provide their own protection where
 * necessary.</li>
 *
 * </ul>
 *
 * <p>When an <code>Action</code> instance is first created, the controller
 * will call <code>setServlet</code> with a non-null argument to identify the
 * servlet instance to which this Action is attached. When the servlet is to
 * be shut down (or restarted), the <code>setServlet</code> method will be
 * called with a <code>null</code> argument, which can be used to clean up any
 * allocated resources in use by this Action.</p>
 *
 * @version $Rev: 471754 $ $Date: 2005-08-26 21:58:39 -0400 (Fri, 26 Aug 2005)
 *          $
 */
public class Action {
}

Struts2.5.30

/**
 * All actions <b>may</b> implement this interface, which exposes the <code>execute()</code> method.
 * <p>
 * However, as of XWork 1.1, this is <b>not</b> required and is only here to assist users. You are free to create POJOs
 * that honor the same contract defined by this interface without actually implementing the interface.
 * </p>
 */
public interface Action {
}

结合以上内容,我们可以看出二者在 Action 的设计方面的差异:

线程模式方面

Servlet依赖方面

可测试性方面

输入捕获方面

表达式语言方面

绑定值到页面方面

类型转换方面

数据校验方面

对Action执行的控制方面

对IOC的应用

IoC (Inversion of Control,控制反转)随着Java社区中轻量级容器(Lightweight Contianer)的推广而越来越为大家耳熟能详。在此,无需再多费唇舌来解释“什么是控制反转”和“为什么需要控制反转”,因为互联网上已经有非常多的文章对诸如此类的问题作了精彩而准确的回答。特别地,读者可以去读一下 Rod Johnson和Juergen Hoeller合著的《Expert one-on-one J2EE Development without EJB》(此书被称为“架构学习上的明灯”) 或 Martin Fowler所写的《Inversion of Control Containers and the Dependency Injection pattern》。

众所周知,Struts2是以Webwork 2作为基础发展出来。而在Webwork 2.2之前的Webwork版本,其自身有一套控制反转的实现,Webwork 2.2在Spring 框架的如火如荼发展的背景下,决定放弃控制反转功能的开发转由Spring实现。值得一提的是,Spring确实是一个值得学习的框架,因为有越来越多的开源组件(如iBATIS等)都放弃与Spring重叠的功能的开发。因此,Struts2推荐大家通过Spring实现控制反转。

为了更好地了解反转控制,下面来看一个例子,如何利用IoC在Action处理过程中可以访问到当前请求HttpServerRequest对象(ModelDriven也是)。在例子中,使用的依赖注入机制是 接口注入 。就如其名称一样,接口注入需要的是已经被实现了的接口。在这个接口中包含了相应属性的 Setter,以便为Action提供值。例子中使用了RequestAware接口(类似的还包括 SessionAware、ApplicationAware、ModelDriven等接口)如下:

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

当我们的Action继承了这个接口后,原本简单的Action看起来就有点复杂了,但是这时可以获取HttpServerRequest对象来使用了,如下所示:

public class IoCForStruts2 implements RequestAware {

    private HttpServletRequest request;

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

    public String execute() throws Exception {

        // 可以开始使用request对象进行工作了...

        return Action.SUCCESS; 
    }

}

虽然看起来现在这些属性是类级别的,不是线程安全的,会出现问题。但其实在Struts2里并没有问题,因为每个请求过来的时候都会产生一个新的Action对象实例以及新的ActionContext实例(ActionContext就包含请求的内容),它并没有和其他请求共享一个对象,所以不需要考虑线程安全问题。

Struts2的拦截器机制

拦截器(Interceptor) 在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作。

拦截是AOP的一种实现策略。在Webwork的中文文档的解释为:拦截器是动态拦截Action调用的对象。

它提供了一种机制可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时,也提供了一种可以提取action中可重用的部分的方式。

Struts1.x的标准框架中不提供任何形式的拦截器,虽然有一个名为SAIF的附加项目实现了这样的功能,但它的适用的范围还很有限。拦截器是Struts2的一个强有力的工具。Struts2许多的功能(feature)都是构建于它之上,如国际化、类型转换器、数据校验、异常处理等。虽然,Struts2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。

谈到拦截器,还有一个流行的词 —— 拦截器链(Interceptor Chain),在Struts2中称为拦截器栈(Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链,在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。这涉及到了对责任链模式的应用,具体请见关于拦截器、AOP和责任链模式的介绍的文章《责任链模式综述(基础篇)》 和 《责任链模式进阶:与AOP思想的融合与应用》。

Struts2 的拦截器实现相对比较简单,当请求到达Struts2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一一地调用列表中的拦截器,Struts 2已经提供丰富多样功能齐全的拦截器实现。这一点在《责任链模式进阶:与AOP思想的融合与应用》中做了详细的阐述。

读者可以到struts2-all-2.5.30.jar或struts2-core-2.5.30.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。作为框架(framework),可扩展性是不可缺少的,因为世上没有放之四海而皆准的东西。

总结

前面已经简要介绍了Struts2的起源,并详细对比了Struts2和Struts1.x的差异。

本文概述了Struts2的高层的框架概念和基础的请求流程,并介绍了Struts1.x和Struts2两者之间在Action方面、对 Servlet 的依赖方面、输入捕获方面和表达式语言方面等的差别,同时指出Struts2加强了对拦截器与IoC的支持,而在Struts1.x中,这些特性是很难想象的。

同时,读者应该明白:Struts2是WebWork的升级,而不是Struts1.x的升级。虽然Struts2提供了与Struts1.x的兼容,但已经不是Struts1.x的升级。对于已有Struts1.x开发经验的开发者而言,Struts1.x的开发经验对于Struts2并没有太大的帮助;相反,对于已经有WebWork开发经验的开发者而言,WebWork的开发经验对Struts2的开发将有很好的借鉴意义。

更多

若读者想对Struts2的拦截器机制、AOP理念和责任链模式内涵进行进一步的了解的话,请移步到文章《责任链模式综述(基础篇)》 和 《责任链模式进阶:与AOP思想的融合与应用》。

若读者想了解OGNL(Object Graph Notation Language)的前世今生及其在Struts2中的应用请看博文《与MVC框架解耦的OGNL:前世今生及其基本用法》 和 《 再述 OGNL:在Struts2中的应用》。

更多关于Struts2的的介绍请见我的专栏《Java Web 成神之路》。本专栏全面记录了Java Web开发相关知识,不但包括对http, servlet,session等基础知识的讲解,还包括对流行框架(SSM,SpringMVC等)、中间件(Redis等)等进阶知识的深入分析。笔者将持续跟进最新Web技术,期望对大家能够起到抛砖引玉的效果。

标签:拦截器,Struts,接口,Struts1,Struts2,Action,对比
来源: https://www.cnblogs.com/tangyouwei/p/the-difference-and-comparison-between-struts-1-and-st