`
huibin
  • 浏览: 754277 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

struts 2.0架构目标

阅读更多

对于一个特定的代码库而言,要谈它的架构目标是很困难的。通常在开发之前,其最终目标就写进了文档中;但这是理想化的状态,当开始开发之后,代码往往就会向着另外的方向发展。然后就有了代码库的典型特征;它们很难被发现,在不同的package或者特性之间有可能表现出不一致,并且更像是脱离计划之外的演变产物。
在本章中,我们将要讲述Struts 2代码库中五种这样的特征。从2002年的代码库演变起始——从最开始的WebWork,到WebWork分离成为WebWork2和XWork,再到最后的Struts 2,这些架构思想一直延续到了今天。
概念分离
以下这些不同层次的功能都是Web开发人员应当了解的:
    ♦ 在请求/响应周期中,所完成的核心任务是执行特定于每个Action的逻辑功能。
    ♦ Action要完成逻辑功能或者访问资源的话,必须要访问或者持有业务对象。
    ♦ 在把HTML中基于字符串的值转换成原始数据类型或其他对象类型,以及把视图对象转换成业务对象或者数据表表示的过程中,这期间需要完成多种转化,映射和变换。
    ♦ 有一些横切(cross-cutting)的目的是为成组的action,或者应用中的所有action提供功能的。

在Struts 2的架构中,以上的每一种概念都是被单独分离的。功能和逻辑不再是Action独享的。让我们看一下上面提到的概念是如何被分离的:
    ♦ 每个Action的逻辑(Per-Action Logic) ——这是最简单的概念;每一个Action都要为它所提供的逻辑或功能负责。
    ♦ 访问/持有业务对象(Accessing/Obtaining Business Objects )—— Struts 2 使用了依赖注入机制来把Action所需的对象注入到Action中去。
    ♦ 转化/映射/变换(Translation/Mapping/Conversions )——这三个概念两两之间都有着细微的区别,但它们都为Action核心逻辑提供了辅助功能。类型的转化和变换是由框架本身完成的。在Action开始进行处理之前,HTML中的字符串值就被转化成了基本类型,然后注入进Action里面——所需的东西就齐备了。映射是通过特定的拦截器完成的。我们需要通过某种方式对Action进行配置,让它拥有一个领域模型,并正确指定HTML中相应的字段,这样框架就会把UI与领域模型进行映射。它甚至还可以贯穿一个对象图。
    ♦ 横切的概念(Cross-cutting Concerns )——横切功能主要是由拦截器提供的。开发人员可以实现拦截器,然后让它们横切所有的Action,横切特定Package中的Action,或者还可以选择所要横切的Action。 另外一个横切的概念是UI布局。在这里Struts 2提供了被称作“主题”的支持标签。不同的主题可以提供不同的布局选项,并可以应用到每一个独立的标签中,或是整个应用程序(把该主题设置为默认值)。

松耦合
WebWork早期的目标之一就是提供一个松耦合的框架。WebWork2.0版本更强化了这一点,把代码拆分成了两个项目:XWork——一个通用的命令框架;WebWork——XWork的针对Web的接口。WebWork在架构上做出的根本性变化创造了一种共生的关系。我们现在所知的“WebWork”实际上是WebWork和XWork的合并。 

XWork作为一个独立的项目,可以作为其他项目的一部分加以利用——事实也是如此。Swingwork7就是这样一个项目。它是基于Swing的MVC框架,在底层使用了XWork。另外一个例子是一个JMS前端,它在Web UI中执行或共享XWork的action。这些都是高度松耦合的精彩示例。Struts 2也是XWork的一个受益者。
松耦合的思想在Struts 2中得到了更好的传播,它贯穿了整个框架的始终——从最开始Action的处理过程到最后一步结束。实际上,在Struts 2中几乎没有什么是不可以被配置的——我相信这是Struts 2中最强有力的地方之一,但也是最虚弱的地方之一。
松耦合的配置有一些常见示例:
    ♦ 把URL映射到Action
    ♦ 把不同的Action结果映射到被渲染的页面
    ♦ 把处理过程中发生的异常映射到被渲染的异常页面

稍微少见一些的Struts 2特有的示例有:
    ♦ 在不想用Spring的情况下配置业务对象工厂
    ♦ 改变URL与Action类的映射方式
    ♦ 添加新的Action结果类型
    ♦ 为新的框架功能添加插件
    ♦ 通过拦截器配置框架层的功能

松耦合系统的好处是广为人知的——增加易测试性,更容易扩展框架功能,等等。但是这里还有一点坏处。强大的配置管理功能,尤其是拦截器在其中至关重要的作用,使得开发人员已经很难理解某个Action的执行过程。这一点在调试时尤为突出。一个不了解内部流程的开发者很难提高调试的速度或效率,因为他根本就无法理解这中间发生了什么。这种问题可能简单如拦截器的配置错误,甚或是拦截器的配置顺序不对。如果我们能够充分理解处理过程中的每一个细节,那么很快就能找到解决方案了。
易测试性 
在过去的几年里,单元测试已经成为了软件开发领域内的事实标准。测试不仅能够保证逻辑的正确性,而且在开发所要测试的类的时候(如果在此之前则更好),通过编写单元测试还可以得到更简洁强壮的设计。
Struts2的前身——WebWork,就是在这种环境下开发的。在与框架元素保持松耦合的情况下,测试变得更加简单。Action、拦截器、结果、对象工厂以及在Web应用开发过程中开发出的其他组件,都可以不依赖于框架进行测试。
因为Action和拦截器是最常用的,所以下面我们来看一下怎么样对它们进行测试。
Actions
Actions在框架中一般都是通过“execute()”方法被调用的,在更改配置以后,任何返回String类型值的方法都可以用来调用Action。站在易测试性的角度来看,这已经无法更简单了。
我们先来看一个例子。下面这个action被用来增加一个数值:
public class MyAction {
private int number;
public int getnumber() { return number; }
public void setNumber( int n ) { number = n; }
public String execute() {
number += 10;
return “success”;
}
}
因为Action都是POJO,所以单元测试只需要实例化一个Action,调用其中的方法,然后确保返回的结果与所期待的一致。Action中的数据资源都是通过setter方法来提供的。所以Action中所需的数据都可以被直接赋值。
在我们的例子中需要两条断言——一个用来判断“execute”方法的输出,一个用来验证我们所期望的Action的状态。下面是单元测试代码:
public class myActionTest extends TestCase { 


public void testExecute() {
MyAction action = new MyAction();
Action.setNumber(5);
assertEquals("success", action.execute());
assertEquals(15,action.getNumber());
}
}
对于资源来说情况就复杂一些了。我们可以用类似于JMock8的第三方库来提供资源的mock实现,然后测试Action与资源之间的交互是否正确。
虽然例子是用JUnit来写的,但是我们同样可以使用TestNG或者其他的测试框架。
拦截器
在构建拦截器时,测试会稍稍复杂一些。但是在代码框架中也为其提供了额外的帮助。下面是两个使用拦截器的场景。
第一个是拦截器在使用时与ActionInvocation对象交互。在执行完以后,你可以通过断言拦截器本身的状态来对逻辑处理进行验证。在这个场景中,拦截器的测试方式和action一模一样。实例化拦截器;创建一个ActionInvocation的mock实现,用它来测试拦截器;调用intercept方法;然后断言所期望发生的变化。所断言的可能是拦截器本身,也可能是方法调用的结果,抑或是可能会抛出的异常。
第二个场景是拦截器与运行环境或者是与拦截器栈中的其他拦截器交互。这种情况下,测试需要通过ActionProxy类与Action交互,同时断言也需要访问拦截器本身没有权限访问的其他环境对象。
XWork库为JUnit测试提供了XWorkTestCase类,为TestNG测试提供了TestNGStrutsTestCase和TestNGXWorkTestCase,用以帮助测试拦截器。它们都为ConfigurationManager,Configuration,Container和ActionProxyFactory类的实例提供了测试实现。XWork
同时还提供了其他一些类,比如XWorkTestCaseHelper和MockConfiguration。
现在我们已经有了建立测试环境的底层架构,测试本身就变得容易了——只需要按照第一个场景中的步骤执行就可以了。唯一的区别就是在调用拦截器的intercept()方法时,同时还需要调用ActionProxy的execute方法,例如下面的代码:
ActionProxy proxy =
actionProxyFactory.createActionProxy(NAMESPACE,NAME,null);
assertEquals("success", proxy.execute());
在这个场景中,测试代码可以断言的期望值包括:Action的结果,Action的值或是值栈中的值。下面的方法可以在Action的执行前或者执行后获取这个Action对象:
MyAction action = (MyAction)proxy.getInvocation().getAction();
下面的方法可以用来得到值栈:
proxy.getInvocation().getStack()
模块化
当应用的规模变大以后,把程序分拆成各个模块的重要性就不言而喻了。这样一来,我们就可以把一个项目中开发的功能或者新的框架特性打包,并且在其他项目中重用。Struts 2已经把模块化作为了体系架构中的基本思想,开发人员可以独立工作,然后在其他人的工作基础上进行构建。
下面是将应用程序模块化的几种方法:
    ♦ 将配置信息拆分成多个文件——它本身不会对应用程序的分包造成影响,但是配置信息按照功能的界限进行拆分以后,管理起来就容易了很多,也减小了开发的难度
    ♦ 把自包含的应用模块创建为插件——所有用来提供某一种特性的功能组成——包括Action、拦截器、拦截器栈、视图模板(除了JSP以外)等等——都可以被打包在一起,并

9 config browser插件的文档地址为[url]http://struts.apache.org/2.x/docs/config-browser-plugin.html[/url]


    作为独立的插件发布。例如配置浏览器插件9,该插件提供了一个完整的模块,该模块可以为所在的应用程序添加一个用来查看配置信息的Web接口。
    ♦ 创建新的框架特性——与特定应用无关的新功能可以组织成插件,应用到多个应用中。

从技术角度来讲,这几种模块化的方式其实是一样的——它们都有同样的配置元素(除了名字可能不同以外,在使用插件时,“struts-plugin.xml”文件会作为配置文件被自动加载),同样的目录结构,并且可以包括同样的框架和应用元素。
上面的两种插件类型的唯一区别在于你从怎么概念上去理解它们,在发行包中放入的是哪些元素和配置文件。
额外的配置元素
因为插件可以为内部的框架功能提供替代的实现方式,所以需要做一些额外的配置。这些配置元素可以在“struts.xml”配置文件中使用,也用在了“struts-default.xml”文件中,但是它们更常用的情况是用来配置插件。
在插件中,替代的实现方式是分两步来配置的:
    1. 使用 <bean … />标签来定义替换的接口实现,并用一个唯一的key来标识
    2. 使用<constant … />标签来在多种可能的接口实现中进行选择

下面我们来看看每一步的具体细节。
<bean … />标签可以用来为扩展点提供实现信息。下面的例子是“struts-default.xml”配置文件中一个对象工厂的配置:
<bean name="struts"
type="com.opensymphony.xwork2.ObjectFactory"
class="org.apache.struts2.impl.StrutsObjectFactory" />
在配置项的属性中包含了用来在Struts 2里创建和使用替代对象实现(alternate object implementation)的所有信息。这些属性包括:
    ♦ class ——类的全名

    ♦ type ——类所实现的接口
    ♦ name ——每个type的唯一简称
    ♦ static ——是否把静态对象方法注入到类实例中
    ♦ scope ——实例的作用域,可以是“default”,“request”,“session”,“singleton”或“thread”
    ♦ optional—— 当值为“true”时,即使创建类实例的过程中发生错误,也会继续装载。

然后,开发人员可以用<constant … />标签来选择使用哪一个配置。这里只有两个属性——“name”属性提供了扩展点的名字,这个扩展点是在新的实现中会被更改的,“value”属性的值是在<bean … />标签中配置的唯一标识。
<constant name="struts.objectFactory" value="plexus" />
<constant … />标签是把一个新值赋给已知属性的一种方式,但并不是唯一的方式。新值还可以在“web.xml”文件的“init-param”中修改,或者作为一个名-值对写入“struts.properties”配置文件。
如果你不是在开发插件,而是在普通的“struts.xml”文件中使用这些技术,那么还有捷径可走。把一般来说会放在<bean … />标签中的类名放进在<constant … />标签中——这样就避免了使用<bean … />标签。
下表列出了可配置的扩展点对应的接口与属性名。
接口     属性名     Scope     Description
com.opensymphony.
xwork2.ObjectFactory    struts.objectFactory     singleton    创建在框架中用到的对象——Action,结果,拦截器,业务对象等等。
com.opensymphony.
xwork2.
ActionProxyFactory     struts.
actionProxyFactory     singleton    创建ActionProxy
com.opensymphony.
xwork2.util.     struts.
objectTypeDeterminer    singleton    判断一个map或者collection

ObjectTypeDeterminer    中的key和元素是什么
org.apache.struts2.
dispatcher.mapper.
ActionMapper     struts.mapper.class     singleton    从请求中得到ActionMapping并从ActionMapping中得到URI
org.apache.struts2.
dispatcher.multipart.
MultiPartRequest     struts.multipart.
parser     per request     解析 多部件 请求(文件上传)
org.apache.struts2.
views.freemarker.
FreemarkerManager     struts.freemarker.
manager.classname     singleton    载入和处理Freemarker 模板
org.apache.struts2.
views.velocity.
VelocityManager     struts.velocity.
manager.classname     singleton    载入和处理 Velocity模板

<constant … /> 标签和 “web.xml”文件中的“init-param”不仅仅可以用来定义扩展点属性。“struts.properties”文件中的所有属性都可以通过二者进行修改。
惯例重于配置
惯例重于配置是Rails带入主流应用开发中的概念。它不是提供那些对于各个应用而言都很相似的配置文件,而是假定在绝大多数情况下,开发人员都会遵守特定的模式。这种模式具有足够的通用性,所以可以被认为是一种开发惯例,框架会默认使用这种模式,而不是为每一个新的应用都提供配置。在默认情况下,开发人员就不必再管理种种配置信息了。如果有的需求与惯例的配置信息不同,那么还可以根据需求进行修改,把默认模式覆盖掉。
Struts 2采用了这个概念。松耦合在给Struts 2带来高度灵活性的同时,也带来了配置上的高度复杂性。惯例在这二者之间做出了平衡,为我们提供了简洁而高效的开发者体验。
Struts 2中“惯例重于配置”的应用可以通过以下几个例子来说明: 
    ♦ 隐式的配置文件加载——不需要显式配置“struts-default.xml”和“struts-plugin.xml”(对每一个插件而言)文件,它们会被自动加载。
    ♦ Code Behind插件——在使用code behind 插件时,它会混合使用action名和结果字符串在结果模板中进行自动搜索,所以“/user/add.action” 这个action的“success”结果会返回“/user/add-success.jsp”结果模板,“error”结果会返回“/user/add-error.jsp”结果模板。
    ♦ 默认的结果和结果类型—— 在配置Action的时候,如果使用默认的“success”结果和JSP结果类型的话,就不需要对它们进行配置
    ♦ 织入(Wiring)Spring业务服务——在安装了Spring框架插件以后,就不必为每个Action所需的Spring提供的业务服务进行配置,这些 业务服务会被自动织入到Action里。

分享到:
评论

相关推荐

    struts 2.0与ajax 的实例

    Struts 2.0 是一个基于 Model-View-Controller(MVC)架构的Java web框架,而 AJAX(Asynchronous JavaScript and XML)是一种在无需刷新整个页面的情况下更新部分网页内容的技术。在这个实例中,我们将深入探讨 ...

    Struts2.0学习系列

    Struts2.0是Java Web开发中非常重要的一个框架,它是经典的MVC(Model-View-Controller)架构的实现,由Apache软件基金会的Struts项目团队开发。本教程旨在帮助初学者理解并掌握Struts2.0的核心概念和技术,虽然教程...

    struts2.0中文帮助手册.rar

    Struts2.0的核心设计目标是提供一个更有效、更易用且更强大的MVC(Model-View-Controller)架构实现。它整合了众多优秀的框架和库,如FreeMarker和Tiles,提供了丰富的拦截器(Interceptor)机制,使开发者可以方便...

    Struts2.0培训文档.rar

    Struts2.0是Java Web开发...这份文档将帮助你深入理解Struts2.0的架构、工作原理以及实际开发中的应用技巧,对于提升Java Web开发能力非常有帮助。在学习过程中,结合实际的项目实践,将更有利于掌握Struts2.0的精髓。

    struts2.0源码 第2章

    首先,Struts2.0是基于Model-View-Controller(MVC)设计模式的,它的主要目标是简化Java Web应用的开发,并提供更强大的控制层。在这一章的源码中,你会看到如何通过Action类实现业务逻辑,以及如何与视图层进行...

    struts 2.0 完整示例

    这对于初学者来说是一个很好的起点,能够帮助理解Struts 2的基本架构和工作流程。同时,随着深入学习,你还可以探索更多高级特性,如国际化、文件上传下载、Ajax支持等,进一步提升你的Web开发技能。

    struts2.0架包

    Struts2.0的核心设计目标是使开发者能够更方便地处理HTTP请求,更好地组织业务逻辑,以及更有效地实现视图与控制器的分离。 在Struts2.0框架中,有几个关键的概念和组件值得深入理解: 1. **Action类**:这是处理...

    struts2.0最新实例2

    Struts2.0是Apache软件基金会的一个开源项目,它是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架。这个框架的主要目的是为了简化Web应用开发过程,提高开发效率,提供强大的控制层来处理HTTP...

    Struts2.0两个小时教学PPT

    Struts2.0是一个流行的Java Web开发框架,它极大地简化了MVC(模型-视图-控制器)架构的实现。本教程重点介绍了Struts2.0中的类型转换、输入验证和拦截器,这些都是构建安全、健壮Web应用程序的关键组件。 **类型...

    Spring2.0整合Struts2.0

    **Struts2.0** 是Struts的下一代框架,基于WebWork技术,提供了一种更简洁、更灵活的MVC模式实现。它改进了Action和结果的管理,支持拦截器(Interceptor)机制,增强了异常处理,以及提供了丰富的插件体系。 **...

    Struts2.0中文教程

    Struts2.0是Java Web开发中的一个强大框架,它基于Model-View-Controller(MVC)设计模式,为开发者提供了构建动态Web应用程序的高效工具。这个“Struts2.0中文教程”涵盖了该框架的核心概念、配置、动作、拦截器、...

    struts2.0+spring2.5+Hibernate3.2

    Struts2.0、Spring2.5和Hibernate3.2是经典的Java企业级开发三大框架,它们的集成应用为开发者提供了强大的模型-视图-控制器(MVC)架构支持,实现了业务逻辑、数据持久化和控制流程的解耦。下面将详细介绍这三个...

    手把手struts2.0+hibernate3.1+spring2.0环境配置和实验指导

    ### Struts2.0 + Hibernate3.1 + Spring2.0环境配置与实验指导 #### 一、实验目的与要求 本次实验旨在帮助学生全面掌握使用Struts2.0、Hibernate3.1与Spring2.0这三个开源框架来构建一个简单的企业级应用。通过...

    struts2.0中文帮助手册 html版

    Struts2.0中文帮助手册是一份非常宝贵的资源,它为开发者提供了全面的关于Struts2.0框架的中文指导。Struts2是Apache软件基金会的开源项目,是一款基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架...

    struts2.0编程实例

    Struts2框架的核心设计目标是简化Java Web应用的开发,并提供一个可扩展和易于维护的架构。它在Struts1的基础上进行了大量的改进,引入了更多现代Web应用开发的理念和技术。 1. **Action与Result**:在Struts2中,...

    Struts 2.0

    Struts 2的核心目标是简化Java应用的开发,使开发者能够更高效地构建动态、数据驱动的Web应用。 **入门配置** 在开始使用Struts 2.0之前,首先需要进行必要的环境配置。这通常包括以下几个步骤: 1. **安装Eclipse...

    Struts2.0学习笔记.doc

    Struts2.0是一个流行的Java Web开发框架,它极大地简化了MVC(模型-视图-控制器)架构的实现。在Struts2中,类型转换是自动进行的,旨在帮助开发者处理请求参数与Action类属性之间的类型匹配问题。文档中的内容主要...

    struts2.0中文文档

    Struts2.0是Apache软件基金会的开源框架,它是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架。Struts2.x系列是Struts1.x的升级版,结合了WebWork框架的核心功能,从而提供了一个更强大、更...

    Struts2.0 文件上传与下载全解析

    Struts2.0 是一个流行的Java Web开发框架,它提供了丰富的功能来简化MVC(Model-View-Controller)架构的应用程序开发。在Struts2中,文件上传和下载是常见的需求,尤其对于处理用户交互和数据交换的Web应用来说。本...

Global site tag (gtag.js) - Google Analytics