深入Struts架构
介绍应用框架MVC和Model 2
理解Struts 原理
使用Struts 控制流 讨论Struts 的优缺点
A common mistake that people make whencompletely foolproof is to un?框架,以及它能给你的应用开发所带来的好处。我们相信一旦你也构和设计,你就可以很好的在你的应用中使用架构有个充分的全面印象,我们将总体介绍响应事件循环的方式。只有彻底理解这个处理原理才能最好的在应用中使用这个框架。应该是个漫不经心的决定。很多人将使用这本书,特别是用是否适合它们的项目。因此, 对专业开发人员。为做出正确的决策,Struts
trying to design something
derestimate the ingenuity of
complete fools.
Douglas Adams, Mostly Harmless
2.1 Talking the talk
本章深入探讨Struts
能“随便谈谈 ”web架 Struts。
为了能对Struts Struts的控制流和它处理请
求-
选择一个web 应用框架不
这章的内容来评价Struts 我们在这章的最后将有一个关于Struts
优缺点的公正的看法,并阐明其总体性能。
Struts 设计针 专业人员应该知晓工具的能力和限
制性。
2.2 为什么我们需要
今天的web 应用基本上都是代表共同理念的关键组件。通常,开发团队需要在有限的
时间里创建应用,然它们不得不正确的构建,并能持续构建它。
Java web 开发人员已经有一些工具可用来建立表现层,比如JavaServer Pages 和
Velocity 模板。也有一些机制来处理数据库?如JDBC 和Enterprise JavaBeans (EJBs)。但我们
用什么来将它们集合在一起? 我们已经有了型材和砖墙…还缺什么?
2.2.1 退一进三
在上世纪80年代,当GUI被发明时,软件架构认为,应用具有3个主要部件:
管理数据的部件,创建屏幕和报表的部件,以及处理用户交互和子系统交互的部件
[Ooram]。
在90年代早期,ObjectWorks/Smalltalk 编程环境将这个3角结构引入为一个开发框架。
按Smalltalk 80的说法,数据系统称为模型 Model,表现系统称为视图 View, 而交互系统称为
控制器Controller.。许多现代开发环境,包括Java的Swing, 都使用Model/View/Controller
(MVC) 架构作为它们的基础架构 。
图 2-1 MVC架构 Java web 开发者已经有很多有用的工具,比如JDBC 和 JSP, 作为 Model 和 View的
2.2.2 进入 Struts
制器。Struts 控制器搭起了Model 和View之间的桥
梁。框架也包括开发人员想用来开发可伸缩的、先进的应用的其他组件。Struts是一个“隐
应用如何准确的和
用户进行交互。这些组件在逻辑名称后隐藏了令人讨厌的、繁琐的实现细节。开发人员可以
编 细节,然后转头考虑它们的应用应该做什么,而不是考虑应用应该如何
做。
据和其
手段,但作为控制器的工具和组件在哪? Struts 的核心是一个MVC风格的控藏支柱”的集合,帮助开发人员将分散的材料如数据库和页面,结合成一个整体的应用程序。2.2.3 Struts控制器组件 Struts 控制器组件是一个可编程的组件集,允许开发人员定义它们的一次性写这些实现 用户通过超链接和HTML form与Web应用程序进行交互。超链接引导页面显示数他内容,如文本和图像。表单通常通过一些定制动作向应用提交数据。 主要 Struts 组件
如图5中所示, Struts提供了开发人员可用来定义超链接,表单,和定制动作这些交互
的组件。我们已经使用这些组件在第1章创建了一个入门程序。第3章,我们还要用他们来创
建另一个程序。然后,在第4章,我们将讨论这些组件的详细配置。随后的章节,将详细讨
论如何将每个组件用在你的程序之中。在第4章,我们将展示如何在运行的程序上下文中使
用这些组件。但是,因为这章是架构性的总体介绍,所以我们继续介绍Struts的主要部件。
图 2-2
注
Struts 组件是通过一个XML 文件进行配置的。实践中,配置项是Struts 框架的有机组成部分。为了
将他们糅合在
2.2.3.1 超链
web页面,
或者是定制动作。 人员可以定义超链接为一个
ActionForward.
path 然后通过
名称来引用Acti
Struts启动时读入。 onForward列表。
可用来创建到欢迎页面链接的
一起,我们在讲述它们的时候,会展示每个组件的XML配置项。 接 对应用开发人员来说, 超链接是指向应用中某些资源的路径。它们可能是 它可以包含特殊的参数。在Struts中,开发。 这些对象都有个逻辑名称和一个path 属性。这使得开发人员可以设置onForward。ActionForward 通常在一个XML文件中定义,这个配置文件在Struts 使用 XML 定义来创建Struts 配置,包括一个ActiActionForward 对象的XML元素看起来可能像:
<forward
name="welcome" path="/pages/index.jsp"/>
这个元素创建一个 ActionForward JavaBean ,其name属性设置为welcome, path 属
标而不用改变所有引用该链接的组件。在大多数Web应用中,像这样的细节被硬编码到JSP
困难并且容易发生错误。在Struts 应用中,这些细节可以通过
应用配置来改变,而不用触及到具体的页面和Java 类。
难题留给了开发人员。Struts framework 提供了ActionForm 类, 它设计来处理从
修订循环的
性设置为/pages/index.jsp. JSP 页面和其它组件就可以引用welcome 转发。Struts 框架将查找welcome ActionForward bean 并检索path 属性来完成这个超链接。这时开发人员可以改变链接的目或 Java code中,使维护变得2.2.3.2 HTML表单 web 协议,HTTP 和 HTML,提供了一个从表单提交数据的机制,但却把数据接收作为一个HTML 表单来的输入,校验输入,重新显示表单以供用户进行修订(如果需要),以及伴随相应的提示和信息。ActionForm 其实是具有一些标准方法来管理校验和JavaBean。Struts 自动匹配JavaBean 属性和HTML 表单控件的属性。开发者定义ActionForm类,余下的就交给Struts 。 例如,这个类将自动用HTML表单中同名的属性来组装username域: public final class LogonForm extends ActionForm { private String username = null;
public String getUsername() { return (this.username); } public void setUsername(String username) { this.username = username; }
}
其它属性也会根据表单中的每个域被自动加入。们想要的属性。所以,完全不需要详细分析HTTP 请求。 ActionForm 是按通常的Java 类创建的。Struts配置通过一系列描述符引用A
这使其它组件可以从标准的JavaBean取得它
ctionForm
: <form-beans> 和 <form-bean> 元素。<form-bean> 元素是框架用来识别和实
ionF 的描述符:
类例化Actorm 对象
<form-bean name="articleForm" type="org.apache.artimus.struts.Form"/>
Struts 配置列出它使用的ActionForm bean的清单,并给每个bean一个在应用中被引用时的逻辑名。 1.0 和 1.1
Struts 1.1 中,ActionForm 可以使用Map (java.util.Map) 来存储属性名,而不是单独定义它们。
一种新的JavaBean, DynaBean, 可以在Struts 1.1 和后来的版本中使用。
你可以使用XML 元素来标识DynaActionForm 的属性。这使你可以使用 Struts 配置文件来定义
ActionForms。 2.2.3.3 定制动作
HTML 表单使用 action 参数来告诉浏览器将数据送到哪里? Struts 框架提供相应
的Action 类来接收数据。框架会自动创建、组装、校验和最后处理Action 对象对应的
ctionForm。这样,Action 就可以直接从ActionForm bean取得它需要的数据。比如下例:
A public final class LogonAction extends Action {
public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { MyForm myForm = (MyForm) form;
// ...
return mapping.findForward("continue"); } } Action 根据返回到控制器的ActionForward 对象作出控制流的决定。这允许Action 选
为保证扩展性,控制器也传递当前的请求和响应对象。实际上, Action 可以做所有Java
可以做的事情。
择一个逻辑名称,象continue 或者 cancel,而不是系统路径。 Servlet 1.0 vs 1.1 在Struts 1.1 中,新的 execute 方法应该是首选,而不是我们例子中的perform 方法。perform
已经不被推荐,但还保持向后兼容,予以支持。execute 方法体允许更好的例外处理。新的
ExceptionHandler 在第9章讲述。 关于Action 对象的详细信息,见第8 章。
onForm,和 Action 对象,Struts控制器层还提供几个特殊的组件,
包括ActionMappings 和 ActionServlet。 Struts 也提供在控制器层的应用本地化。
2.2.3.4 ActionMappings
来进行引用。 资源包括HTML 页面,JSP 页
URI, 或者说路径,Struts 框架提供了一个
ActionMapping 对象。 象ActionForward 和 ActionForm一样, ActionaMapping通常也在
L配置文件中定义:
除了ActionForward, Acti 在一个web 应用中,每个资源必须通过URI面,和定制动作。为了给定制动作一个XM
<action-mappings>
<action
path="/logonSubmit"
type="app.LogonAction"
name="logonForm" scope="request" validate="true" input="/pages/logon.jsp"/> </action-mappings> 这也允许同一个Action 对象定义为不同的ActionMappings。例如, 一个映射要求校验
而另一个映射不要求校验。
ervlet
虽然它也可以子类化,
但大多数Struts 1.0 的开发人员将ActionServlet 处理为一个黑盒:他们只是配置它,然后让
自己工作。
在Struts 1.1中,ActionServlet 是比较易于扩展的。第9 章将讨论Struts 1.1 ActionServlet
的扩展点和配置选项。
Web 应用也通过各种提示和信息与用户进行交互。Struts 组件均有内建的本地化特征,
以便Struts应用可以为国际化用户使用。我们在此书中贯穿使用本地化特征。本地化的详细
讨论见第13章。
Form,定制的服务器端动作定义为Action 类。
需要访问JDBC和EJB的开发人员也可通过Action对象进行。这样,表现层不需要和Model
2.2.3.5 ActionS Struts ActionServlet 完全在幕后工作,它将其他组件绑定在一起。它 新2.2.3.6 本地化 2.2.4 用Struts开发Web应用 要使用Struts开发web 应用,开发人员将需要的超链接定义为ActionForward,HTML 表单定义为Action
层打交道truts Actio 。S n 对象将收集View 需要的数据,然后将它们转发到表现页面。Struts
JSP 页面一起使用,简化 提供 JSP 标记库,它们和 HTML 表单和存取Action 要转发的其它数据。其它表现机制,比如Velocity templates, 也可用来访问 Struts 框架,来创建动态的web 页面。这种处理流程入下图: 传给视图
第10章和第11章学习如何创建
Struts的表现页面。
架构前,让我们看看一个Web应用框架必须说明的问题。
2.3 为什么需要框架
论了为什么框架很重要。但为了真正理解一个解
决方案,我们需要了解问题所在。为web开发应用虽然是值得的,但也要迎接各种挑战。让
挑战。
2.3.1 Web? 永无休止的修补
Web 开发者受到两种web缺陷的影响。首先,我们希望使用浏览器作为客户端。其次,
必须使用web协议进行通讯。
Web 浏览器通过HTTP协议通信,并用HTML显示页面。Web浏览器发送HTTP请求,
加工和显示它收到的响应。在处理很少改变的预先编好的页面时,这是个很好的平台。但
我们大多都是编写动态程序,页面针对不同的用户是不同的。虽然有一些现成的动态特征的
段,web 仍然受到HTTP/HTML 的制约。
如下表所示: web 协议和客户端的限制,确定了如何编写Web程序。
表格 2-1 HTTP/HTML 的限制
图 2-3 数据回 关于和Struts中如何使用各种数据系统,见第14章。 在深入Struts 第1章,我们介绍了应用框架,简短讨我们快速看看是什么使web 开发富有我们并手限制 导致的困难 协议 缺省情况下,HTTP接收来自于网络上各种客户端的连接。但各种服
务器间的行为是不一样的; 首先,HTTP用简单的文本域来传输数据。传输二进制文件需要复杂
的协议扩展
HTTP协议是无状态的,需要额外的努力来跟踪程序的用户
HTTP信赖并期望客户能提供正确的信息 客户端 浏览器是个独立的程序,处于应用的控制之外
所有的浏览器都是不一样的,都只支持官方标准的一个子集
从浏览器的输入可能是不正确或者不完整的。甚至可能是敌意的,
和对程序有害的信息
HTML不能够建立一些在桌面环境中有的接口元素
用缺省数据建立HTML控件对应用来说是个考验 很不幸,这种状况现在并没有些许改变。Web开发人员在想战胜挑战时必须看到这些缺
对编写强壮的Web应用有太多障碍,使用框架便显得至关重要,免得你的应用陷入
无休止的工作和改进之中。
我们面临的挑战是很巨大的。但同时也是值得的。HTTP 协议和
HTML 客户端使所有的人都可以访问你的应用。没有其他哪个平台能声称这样。
解决方案
,Java Servlet 平台[Sun, JST] 扮演了一个基本框架,为Java web 应用提
供了大量的能力。Servlet 提供了一个处理HTTP请求和确保响应的基本接口。它在HTTP之
话” 上下文,帮助跟踪应用程序的用户。当然它也提供其他的上下文,帮
助应用传输数据到浏览器或者应用中的其他servlet。Java web 应用也具有对基本安全特性的
不同的服务器上的管理是不一样的。
为了将这些内容集成在一起,Servlet规范引入了一个容器来管理它们。容器也可以提供
其他服务,比如作为一个JSP的处理器。Servlet 容器可以包含它自己的web server,也可以
对数据库访问, Java 应用在其建议中有另外一个通用的框架: JDBC。开发者可以写
准的SQL 接口,而将烦人的细节留给适配器来处理。这使得可以很容易的改变数据库厂
都可以和EJB一起使用。
总之,这使得基于Servlet的web应用非常轻便,并相对易于编写和维护。Servlet 和 JSP
角色。 象Strtus这样的Java web 应用框架构架于Servlet之
框架也包括一个类结构树,这些类你可以在
中实 扩展。通常, 应用框架的目标是帮助你将你需要的数据从浏览器发出,
它们既不阻碍数据库访问,也没有提供帮助。而某些框架, 如
s 库访问,而将其它任务留给开发人员或者其他框架。
2.3.3.1 通用框架策略
陷。因为 在开发Web应用时2.3.2 Servlet 如第一章所述上构建了一个“会统一访问,而这些安全特性在简单的作为一个现存服务器的附属组件。 标商,而不用重写源代码。 为了取得远程服务器的高性能数据库访问, web 开发人员可以使用EJB平台。大多数ava 应用框架,包括Struts, J 在编写应用中扮演了完全不同的上,给开发者提供一个无缝的集成环境。 2.3.3 Servlet 框架 大多数,不是全部, Java web 框架使用 Sun Servlet 平台为基础。这些框架都绑定一些预制的servlet,你可以插入到你的应用中去。你的应用现或者进入到编程结构之中,这样你的应用就可以使用它?或者从编程结构中发出,进入到浏览器之中,这样你就可以看到。 一些框架,如 Turbine [ASF, Turbine],也提供helper 类来运行于 JDBC 数据库。其他框架, 如Struts, 则是模型中立的。dbForm [dbForms],则专注于数据
如下图所示, Java web应用框架使用一些通用技术来帮助产品易于设计、编写和维护,
式(Front
外部表现系统
让不同的人同时工作在同一应 a工程师可以工作在和中心控制
相关的类,而页面设计者则专注于JSP。除了JSP,其他表现系统,如Velocity Templates 或
X
些书象 Design
Patterns [Go4] 和 Core J2EE Patterns [Go3]给出的范例中根深蒂固了。许多开发者在讨论并
些 第一次在Web环境中实现它们。使用设计模式,如MVC,使
容 情来构建你的应用。在桌面环境中使用设计模式的优点已经众
所周知了,但在Web环境部署这些模式却对大多数开发者来说还是不确定的。
包括: 外部配置文件 提供开发人员不想嵌入源代码中的实现细节。 中心控制器 提供一种方式,将HTTP 请求排入一个易于管理的队列。这种设计有时叫前端控制器模 Controller [Go3]) 用的不同部分。如, Jav器者LST, 都可以和Struts一起使用。 框架通常有各种组件,但基本上都共享这个特性。这些公共策略早已在一使用这模式,但也许还没有你可以易的通过做正确的事 图 2-4 通常使用配置文件,控制器和表现系统的框架 2.3.4 黑盒-白盒统一体 框架有时分为两极标有白盒和黑盒的统一体[Fayad]。白盒框架严重依赖于面向对象的
语言的 承和动态绑定。黑盒框架则注重定义可插入组件的接口,然后基于这些接
口提供基本的起始组件。接口和基本组件通常提供热点(hotspot )方法,这个方法可以直接
使用或者重写后提供特别的行为。
特征,如继
定义
热点有时也称为是灵活点或者扩展点,它其实是框架中的一些位置,在这里可以加入一些代码来定制框架。热
点(热点 应用中可 系统)每个以被框架所支持的不同特征。本质上,它们代表框架所解决的问题。许多面向对象
框架有一个核心系统和一些热点子系统组成[Braga, et al] 像许多正在使用的框架, Struts 使用混合的黑盒和白盒技术。但总体上,框架将偏向
统一体的黑盒一端。
黑盒框架通常依赖于设计模式。Struts 也不例外。事实上,设计模式通常被用来作为框
架的总体描述 [Johnson
在Struts 框架之中。
2.4 Struts, Model 2, 以及 MVC
Struts 关于自己要说的第一句话就是:框架
… 鼓励应用架构基于Model 2 方法,即经典的MV 设计模式的变体
这句话打消了一些web 开发
惑了。 事实上,没有深入了解MVC 和Sun Model 2,要理解很多Struts的文章都很困难。
2.4.1 MVC 的演化
如2.1节所说, Model/View/Controller原本是建立Sm 应用的框架。框架支持代表
应用状态、屏幕表现和控制流的3个类,分别叫做 Model, View, 和 Controller。
]。为保持这个趋势,我们先介绍一下设计模式,以及它们是如何用C 者的疑虑,对那些还没深入Model 2 或 MVC的人来说却更加疑alltalk nts of R
图 2-5 MVC 三角
Smalltalk MVC 框架 在流行的书Design Patterns: Eleme eusable Object-Oriented
Software[Go4]是作为案例来研究的。Design Patterns 这本书有四个作者,被称为“四人帮
GoF”。
Design atterns中的MVC 例子称赞 通知/ 订阅者(notify/subscribe )协议和观察者
Observer模式的使用。例子的基础是,对同一数据,系统可能需要不同的显示视图,比如条
形图、饼图、数据表格等等。这是一个划分应用的精彩理由,经常被重复引用。
P
图 2-6 The Model data can be used in several d如果ferent views. 在图2-6所示的例子中,每种视图可能在同一时间显示给不同的用户。应用必须保证在
最近的模型改变状态。
以应用它其他平台上面。
贝粘贴”。
t
HTML的任务。在例行课程中,结合使用 JSP
t 开 l 2 (单独使用JSP称为Model 1)。
iew-Controller 架构。
在很多场合,现在交互使用Model 2 和 MVC这两个词已经很平常了,虽然还有一些争
MVC,以及是否支持经典的观察者通知模式。没有观察者通知的
od C。.
认为区别于MVC 的一个原因是,观察者/通知模式不能在web 环境内工作
其下面的数据或者模型改变时视图的更新。为改变模型,用户提交一个请求给控制器,由控制起来配合改变模型。数据视图必须跟着改变,以反映 Smalltalk MVC 方案使用观察者通知模式。在这种模式下,每个视图注册为一个模型数据的观察者。然后模型可以通过发送消息给所有这册观察者,通知它们相关的改变。其为 Smalltalk MVC 框架已经通用化了,他也可2.4.2 Model 2的出现 JSP的意图是使创建动态页面更容易。JSP 首先是作为servlet的替代引入的,还有就是MS的ASP。Servlet的强大功能当作易于创建服务器页面的工具提供给开发者。但强大的功能伴随着巨大的责任。很多团队发现,如果他们一不小心,他们的项目就会因为纠缠如麻的页面变的容易崩溃。进一步的特性需要使用复杂的脚本程序。但脚本程序是非常难于重用的?除非你在页面间把代码“拷 工具页面也可以包括进来,但他们很难被组织在一起,并且造成非常丑陋的“资源”树。有些东西会出错。 很多开发人员很快意识到, JSPs 和 servlets 可以一起使用来部署web 应用。Servle可以应付控制流,而 JSP则可专注于讨厌的编写和 servle始被称为Mode 当然,从Sun哪里仍然没什么新东西... 而且很多人很快指出 JSP Model 2 类似于经典的Model-V 论,即一个应用是否是Mel-View-Controller 有时被称为MVC2 或Web MV2.4.3 应用层?和视图去耦合 Model 2 被的很好。HTTP 是一个 “拉” 的协议: 客户请求然后服务器响应。没有请求就没有相应。观
察者模式需要一种“推”协议来进行通知,以便服务器能在模型改变时将信息推送到客户端。虽然也有一些方法能模拟将数据推送到客户端,但这和基本情况相悖,并且会视为是权宜的
补。 修 被表示为:一个互相连接的三角形。在
应用中维护范式中的“通知改变”部分是非常困难的。
这些东西在所有资源都在一台服务器上,而且客户端保持一个开放连接的情况下工作得
常
包括web应用,在视图进行状态查询的概念时退缩了。绝大多数
况
引入层模式将状态改变和状态查询的职责加于控制器之上,并伴随
着改变通知。
图 2-7 MVC 通常表示为3个互相连接的组件 图2-7是典型的Model-View-Controller范式,经常web 非好。如果资源分布在不同的服务器上,并且客户端不能维护一个开放的连接情况下,工作的并不理想。 许多分布式系统架构, 情下,远程应用是按层模式[POSA]设计的。基本上,层模式下,层内的对象可以和同一层或者相邻层的对象进行通信。在一个复杂应用中,这可以在添加组件时,防止依赖关系呈指数增长。在设计远程应用时,分层是一个核心模式。 从MVC 上下文中,
图 2-8 Web 应用的层模式
` 如图2-8 ,分层的web 应用使用一种比传统MVC模式更加“扁平”的模式。控制器被
必须通过
控制器。另一个改变是, 它使用从控制器传递的
数据而不是直接来自于模型层。 ,允许控制器选择数
据和显示这些数据的视图。
2.4.4 Struts 如何实现
Struts 通过提 这个控制器可以用来管
理JSP页面和 和ActionMapping来保
证表现层之外的控制流决策来实现 引用一个逻辑目标。控制器组
件在运行是提供准确的URI。
夹在表现层(View) 和 应用逻辑 (Model)之间。 每个组件的主要职责并没有改变。流程有轻微改变,即查询状态和改变通知都当视图,或者表现层需要加工动态页面时,这种改变去除了View 和 Model的耦合 Model 2, MVC, 和层 供一个控制器Servlet实现了Sun的 Model 2 架构,其他表现设备之间的流程。Struts 通过使用ActionForward MVC/层 模式。JSP可以表列出了Struts的核心类,即对应的经典的MVC组件职责。 表格 2-2 核心 Struts 类和MVC的对应 类 描述
ActionForward 用户指向或者视图选择
ActionForm 状态改变的数据 ActionMapping 状态改变事件 ActionServlet 控制器,接受用户请求和状态改变,以及发出视图选择 Action
控制器的一部分,于模型交互,执行状态改变或状态查询,以及告诉
ActionServlet 下一个选择的视图 除了这些核心类, Struts 使用一些配置文件和视图助手(view helpers)来沟通控制器和模型。下表列出了Struts 配置文件和描述了他们在架构中的角色。 表格 2-3 Strtuts配置文件 文件 目的 ApplicationResources.properties 存储本地化信息和标签,以使应用可以国际化 struts-config.xml 存储控制器对象的缺省配置,包括模型支持的用户指向,状态改变,状态查询 为将Struts配置数据暴露给视图,框架以JSP标签的形式提供了大量的助手类,如表: 表格 2-4 Strtus视图助手 标记库描述符 目的 struts-html.tld 扩展HTML Form的JSP标记 struts-bean.tld 扩展处理JavaBean的JSP标记
sts-logic.tld rut 扩展测试属性值的JSP标记 将以上内容放在一起,下表按层列出了Struts 组件: 表格 2-5 Struts 组件,按层索引 视图层 控制器层 模型层 JSP 标签扩展
ActionForwards
ActionForm classes
ActionMappings
ActionServlet
Action classes ActionErrors MessageResources
GenericDataSource
JSP, Velocity 模板, 以及其他表现系统 各种工具类, 比如CommonsDigester和
CommonsBeanUtil 开发者提 供 的其他数 据 服务和
API 注,根据层模式 ( 2.4.3), 组件应该只能和相同层和相邻层的组件交互。因此, Model 组件不能直接和View组件进行交互。 意
先认识这片森林。你读完此书后,我们建议你再次回来,看看每一部分是如何切合
这个总图的。
2.5.1 总图
实践中,控制器与视图的交互通过请求,会话以及Servlet平台提供的应用上下文进行。 (2.3.2)。 控制器和模型的交互通过文件和存储系统完成 (比如装入XML文档或者属性文件),或者通过其他服务,如TCP, 创建一个到JDBC数据库的连接。 2.5 Struts 控制流 因为web 应用是动态的,所以很难表现“One True Control Flow” 。依赖于环境,不同的方式下有很多不同的事情发生?特别是在web 应用中。但是事情仍然有一个通用的秩序。 如果你是个Struts,应用框架,甚至web 应用的新手,这些流程刚开始可能难以跟得上(理解)。亟待解决的各种问题不一定那么明显。我们将在本书中详细涉及。首先,在介绍树木之前我们进
-响应流
图 2-9 Struts 请求-相应流程 图2-9以UML以次序图的方式展示了Struts 请求-响应流程。我们来按这个请求程走一遍。 括号内的数字请参照图11中的相关地方: 客户请求匹配Action URI 样式的路径 (1). 容器将请求传递给ActionServlet. 如果这个是模块化应用,ActionServlet 选择响应的模块。 ActionServlet 查询路径的映射。 如果映射标明了一个form bean,ActionServlet 看是否已经有一个实例,或者创建一
个新的实例 (1.1)。如果已经有一个form bean,ActionServlet 重设它,并根据HTTP请求重新组装它。 如果 mapping 的 validate 属性设置为 true, 它将调用 form bean 的validate 方法(1.2)。 如果失败,Servlet 将控制转发到input 属性标明的路径,控制流终止。
如果mapping 标明一个Action 类型,如果它已经存在或已经实例化,它将被重用(1.3)。 Action的perform 或 execute 方法被调用,并传递一个实例化的form bean (或者 null)。 Action 可以组装form bean, 调用业务对象,以及其他需要做的事情。 (1.3.1-1.3.4)。 Action 返回一个ActionForward 给ActionServlet (1.3.5).
如果ActionForward 指向另一个 Action URI,重新开始; 否则,显示页面或者其他
资源,流程结束。通常,结果是一个JSP页面,或者Jasper, 或其它类似技术 (非 Struts)
加工的页面。 (2, 3).
如果JSP 使用Struts HTML 标记, 并且在请求中看到正确的ActionForm (1.1),他们
会从ActionForm中组装HTML控件。否则, <html:form> 标记将创建一个。从
Struts 1.1开始, 如果form 标记自行创建一个ActionForm ,它将调用ActionForm的
Reset方法。如果你只是想创建一个空白的表单 (1.1),你可以使用标准的ForwardAction(见第 8章) 来通过Action传递控制,然后离开页面。 2.5.2 出色的细节 他们说,恶魔藏在最隐秘的地方。 前面章节的大纲和图示很好的显示了Struts的概揽,但忽略了重要的细节。让我们更深
入到更好的地方。因为这里是HT 始。
servlet mapping。 容器使用这个设定来决定哪个请求将被送
到哪个servlet:
TP, 所有东西都是从请求开2.5.2.1 请求由容器接收 Struts 框架的核心组件是 ActionServlet。象所有的servlets, 它生存在容器中, 比如Tomcat, Resin, 或者 WebLogic等。当容器启动时,读入部署描述符 (web.xml),告诉容器要装入哪些个servlet。 一个标准的servlet 设定是<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/do/*</url-pattern> </servlet-mapping> 这里,我们让容器将ActionServlet映射到那些符合/do/*样式的请求。这些请求可以是:
/do/This
/do/That
/do/somethin hatever.
许多应用喜欢使用前缀:
g/W
<servlet-mapping> <servlet-name>action</servlet-name>
<url-pa -pattern> ttern>*.do</url
</servlet-mapping>
URL 样 以使用象th
何有效的扩展名,但.do 是比较简单和常用的选
当一个请求随着符合Servlet上下文的路径组件提交时,容器将其转发给ActionServlet。
可以有其他的servlet
来处理其他格式的请求路径。不 求将直接送给容器默认的web
server。
2.5.2.2 请求被ActionServlet 接收
ing, form bean, 最
式也可is.do 或 that.do 或 /something/whatever.do的样式。可以用任择。 不匹配的请求则不转发到ActionServlet。比如,匹配*.jsp的请求将直接转发给容器的 JSP 服务,比如Jasper(如果你使用Tomcat 或者WebSphere的话)。在应用中匹配所有servlet mapping 的请 当ActionServlet 收到一个请求, 它通过一系列的流程处理locale, mapp
后是Action来运行这个请求。这里某些步骤只在Struts 1.1 应用才有:
处理多部分请求. 如果请
Servlet 用一个特殊的句柄包装这个请求,避免处理错误。
求是个多部分请求 (比如,一个表单加上一个MIME附件), 处理路径 ActionServlet 首先检查这个请求路径是否是一个应用模块。如果是,相
应模块的配置被选中。[Struts 1.1]
处理场所. 默认下,Ac 标准的locale 对象在用户会话
的上下文当中。如果没有, ActionServlet将放入一个。这个对象将为每个用户提供
化表现。
tionServlet 会检查是否有一个本地
处理内容和不缓存 默认的MIME 类型和可选的请求头将加在响应之上。
处理映射( Mapping pping,是否有注册的路径符合
正处理的请求。如果没找到, ActionServlet 转发到默认(或 “unknown”) Action(如
有默认或未知A ad request” 错。如果找到相关映
射,将被放入请求之中,供后面引用。
) ActionServlet检查ActionMa果设定ction),否则,产生一个 “b 处理角色. ActionServ 可以访问action. [Struts 1.1] let 检查是否用户被授权
处理ActionForm. ActionServlet 检查是否mapping 标明一个ActionForm.。如果是,
之内(默认是会话)。如果不存在,
ActionServlet 创建一
servlet 检查是否已经有一个存在于特定的范围个。 处理组装. ActionForm的 reset 方法被调用,然后通过反射机制被自动组装。匹
配 orm属性的参数将被使用。其他参数和属性被忽略。 ActionF
处理验证 ActionForm的 validate 方法被调用。如果方法返回false, 控制传递给
ActionMapping的input 属性 ction 未被处理。 标明的路径, A
处理转发和包含 如果ActionMapping 标明 或include 属性,控制被传
递给其他资源。否则ActionS 给一个Action 对象。
forward ervlet 将请求委托
处理 Action. 如果mapping 标 型, ActionServlet检查是否已经有一
个被实例化了。如果没发现, Action 对象将被实例化。每个类只能有一个Action 对
模式),它通过多线程处理所有对它的请求。
perform 或 execute 方法,传递请求, 响应, mapping, 以及form bean。
Action 执行要求的行为,可以包括:
明一个Action 类象 (SingletonServlet调用 Action的
访问数据系统,比如JDBC 数据库 在请求中创建被视图使用的对象
如果需要,在会话中创建对象
根据需要更新会话对象,比如用户的场所
执行需要的业务功能
处 其他错误条 理以外和件 发送一个直接发送一个响应,或者返回一个ActionForward 给servlet
务,可以放在业务对象中的代码都应该放入业务对象。
ction 是一个控制器类,不应该用来处理业务的核心逻辑。
Action 返回ActionForward
ctionForward ,重定向或者转
这里某些行为,象访问数据库,通常由Action 调用的业务对象来处理( Business Delegate 模式)。 Action 处理一些web特定的任A2.5.2.3 Action完成后,它返回一个ActionForward。如果 ActionForward 为null, ActionServlet 假定响应产生了,但不做任何事情。否则, ActionServlet读入 A
发请求到相应的资源。 如果请求是另一个Action URI, 容器将请求返回给ActionServlet。否则容器发送请求到其
它servlet或service。
展用来编写页面的动态部分。有时,也使用JSP模板,以便页面可以从其
它组件进行构建。
数据在JavaBean中传递到请求上下文中的页面。这就是熟知的视图助手
(View Helper )模式 [Go3]。 标签扩展简单的调用JavaBeans的方法,并返回格式化的数
如果ActionForward 设为重定向(redirect), 请求被发送回客户端,并提示重新提交一个新请求到特定的地址。 2.5.2.4 由Jasper (或类似的东西) 加工JSP页面 ActionServlet 发送一个请求 到 JSP, 请求是被另外的服务处理, 如 Jasper。典型地, Struts和其他标签扩 通常, 动态据。而数据如何被放入页面中那是表现逻辑的事情。数据本身的格式通常是业务逻辑的一部分,所以委托给了bean。 Struts 标记也可以访问框架提供的视图助手。这些包括本地化标签和提示,错误信息,以及超链接路径。另外,Struts 标记可以计算表达式,通过列表反复,以及在HTML表单中组装控件。 2.5.2.5 其他 servlet 加工响应 处理完Action后,请求可以被送到应用中的其他 servlet或服务。其他表现系统,如 Velocity templates, 可以通过servlet 上下文访问框架资源。 2.5.3 Struts 是富有效率的吗? 详细描述完Struts处理流程后,你可能会想知道这些的花多长时间。通常,Struts应该能提升大部分正确设计的Web应用的性能。在本节中,我们检查一些关系到框架效率的特殊设计点。 定义 Performant 是一个法语词,意思是有效率(efficient)。软件工程常用这词来表示一个流程或者设备在实际中执行得很好。 Struts 不仅是线程安全(thread- d-dependent )的。
线程化。这种核心策略节省了资源,
并提 最 用一个单独的Action来路由各种相关操
作来 挥
Acti 类层次.
ru
用户不得
资源是有限的,并允许它们更好的使用。
Struts 标
ru 至消除
safe)而且是线程依赖(threa Struts使用轻量的Action 对象,而不是各个单独的servlet,来对请求处理响应。 Struts 实例化每个Action类一次,并允许其他请求通过原有的对象供大的吞吐性。一个正确设计的应用将通过使发这种特征。 onForm bean最小化子类代码并缩短子Stts 框架的一个关键点是可以从请求中自动组装ActionForm bean 。没有这个组件, 不自行编写代码并实例化来组装每个bean类。小心使用反射机制会节省不少资源,签库提供通用功能 Stts一起提供的bean 和 logic 标记库符合大部分JSP 标记的需要。它们减少甚
了编 额
的标签来的有效率。
Struts 组 用来说都是可重用的.
这个方法用来从 组
装一个F
Struts 本 余JSP.
个单独的
Struts 设
Stru 。这使得开发
人员可以扩展存在的类而不是重新编写新类。而且,Struts 也和应用共享资源。这时开发人
使 ,而不用编写和实例化它们自己的类。
标准兼容
好的文档.
有对后端模型做任何假定,一个应用可以按其最有效率的方式实现模型层。
Struts Actions 可以调用一系列助手类来访问需要的数据。一旦数据被检索到, 对JavaBean
易保持值对象,这样来减少了大量的模型层调用。
2.6 Struts 的长处和弱点
一样, Struts 是个解决方案包。它也有其长处和弱点。这里的某些观
点具有主观性,但也希望能对你有些帮助。
.6.1 弱点
已
ease中解决。下表列出了Struts 1.0 的弱点,并在Struts 1.1种解决了。如果你
过Struts,这里某些问题是很精彩的,现在Struts 1.1可以更加符合你的要求。
-6 Struts 1.0 的弱点,在 Struts 1.1 中解决了
写外标签的需要。JSP 规范在JSP重用标签 。使用相同的通用标签3次比使用3次不同件对应框架绑定的工具可以在大部分应用中使用。 BeanUtil.populate 方法就是个例子。HTTP请求组装一个ActionForm Bean,但也可以用来从其它类型的映射中ormBean。重用组件可以减少开销和节省资源。 地化策略减少了大量冗通过允许本地化页面在运行时才获取,国际化应用可以为每种可能需要的语言只提供一页面。同时,相同的消息系统也可以用于处理错误信息。同一对象提供了双重用途。计为一个开放架构. ts 组件设计来是可以被应用子类化的,以便可以提供其它的服务功能员可以用存在的组件Struts是轻量型架构. 类似的框架也许提供数百个类和几十个包。整个Struts 框架 由5个标记库和5个核心包组成。 Struts是的t. Strtus在许多运行标准组件的容器上都工作的非常之好。 Struts是开源的,具良 这意味着开发人员可以检查源代码,找出一些潜在的瓶颈。而且Struts是模型中立的。因为Struts 并没的依赖,使Struts更容 象一些复杂系统2 不管有多么喜爱Struts,重要的是看到框架是干什么的,它的瑕疵和所有。有些弱点经在Struts 1.1 rel以前层使用表格 2弱点 说明
Logging(记录) Struts 使用容器的缺省记录系统,没有提供一个自己的记录包来
为应用提供记录机制。
(Struts 1.1 实现了 Commons-Logging 接口包)
每个应用装入一个单独的配置文件 大型项目可能需要使用多个不被整个团队共享的配置文件
(Struts 1.1 支持多配置文件)
每个场所装入一个单独的资源文件 大型项目可能需要使用多个不在整个团队共享的资源文件。
(Struts 1.1 支持多资源文件)
没有服务管理器 ActionServlet 必须被子类化来提供附加服务,比如用户记录器或
者身份认证系统
(Struts 1.1 提供一些新的扩展点和组件)
ActionForm red tape Struts 1.0 希望开发人员创建定制JavaBeans 与HTML 输入表单
一起使用
(Struts 1.1 支持 Map和 DynaBean 来代替定制JavaBean.)
表2-6列出了框架当前的弱点。在下一节,我们将详细的讨论它们,并象资产一样描述。“Goofus” 或者 “Gallant,” 选择在你。 表格 2-7 Struts1.1的弱点 弱点 说明 没有事件模型 Struts 紧密和HTTP的请求-响应模型结合,这限制了开发人员更好地处理事件 调试 不支持自动调试(除错),开发人员不得不手工创建“断点”,
并向容器的记录系统写标准输出
没有缺省的数据模型或者具体的推荐 访问持久数据模型留给了开发人员 单一ActionServlet 一个应用终止可以使用一个单一的ActionServlet,这个限制可能导致配置冲突 需要理解Struts组件 开发人员需要理解一些特殊的类以及他们如何交互。 不能 优 提供先技术支持 ASF是个志愿者组织,没有全职人员提供可担保的响应 Mailing list已经成为知识的障碍 Struts 有一个日益增长的邮件列表,但要在其中找到最好的间以
非常困难。
正式 版 发布本并不快速 Struts正式发布版相对于其他项目来说先得慢了。开发人员必须经常检查“每日构件”或的最新改进。 i18n 限制 Struts 的消息资源对建立国际化的资源和错误信息非擦好,但不
适合于处理大文本块 JSP mindset 因为使用MVC架构, 使得资源对所有表现层都是有效的。这是个
长期的弊病对JSP来说。
JSP意外本地化 很多系统级消息,象JSP意外,都没有本地化,通常显示为英语
标记 冗 属性长 许多标记扩展要求很多参数,对编程来说很笨 perform 和 execute 方法体 Struts 架构的关键是将请求委托给一个 Action类或者叫分发者
dispatcher。Action 类是Struts支持的唯一分发者,并仅通过其
perform 方法来调用。这将应用限制在只能和perform 方法传递的数据一起工作。即使有办法超出这个限制, perform 方法也
是个瓶颈。 一个通常的请求要求ActionServlet组装几个ActionForm。但是因为 perform 接受单个ActionForm 参数,如果不经过较大的框架
革新是不可行的。 Struts 1.1 添加了一个execute方法,它有助于改善perform的其他
主要缺陷:因为他返回意外。然而,主要的问题已就存在。
模糊的术语 Struts 框架在明显的增长。而给一些应用选项和
类的名称却容易让人混淆。例如,web.xml “ 中的validate” 选项
却和Action 对象的validate 方法无关,而和如何解析配置文件相
关。同样,神秘的 “ null”
选项则表示当消息关键字未找到时,是否返回一个错误信息。
有个趋势是在类层次树种使用复合名称。在Action包中的每个类
都有个前缀为 “ Action,”这却是多余和容易混淆的。同时,在
Struts配置文件中, ActionMappings 定义的元素名是
“ Action” 而不是“ ActionMapping” 。如果开发人员引用一个 “ action,” 很难区别它们是指Action 类或是配置类的ActionMapping。 在 Struts 配置中, “ name” 域标识ActionForward 和
ActionForms“ path” 域标识 ActionMapping。“action-mapping
元素的 name” 属性则指出使用哪个ActionForm 。 ActionForward 的URI域也称为 “ path”,但可以包括伴随path
的查询组件。到ActionMapping 的 “ path” 不包括servlet 样式,
象 *.do, 但是ActionForward 的path 却包括 *.do 扩展名。 应用资源其实是真正的消息资源。
等等。 凡此种种,这些小矛盾可以把一些新手搞糊涂,并且使框架难以
学习 2.6.2 Struts的强项 强 项 说明 以HTTP为中心 Struts设计围绕标准 HTTP 请求-响应模式,为许多Web开发人员所熟悉 标准记录 Struts 可以使用容器的缺省记录系统,而不需要配置和理解其他包
可选的调试记录 Struts 可选记录大量状态处理时的信息,它们可以有助于进行调试 模型中立 Struts 并不倾向于哪个特定的持久层 在一个中心配置中汇集实现细节 Struts 配置封装了应用,或者应用模块[Struts 1.1]的实现细节。所以它
们可以作为一个整体评价和管理
允许为每个场所配置不同的消息
资 源
不同的语言翻译可以工作在他们自己的消息资源文件版本上。添加一个
新场所的支持仅需简单地添加一个资源文件 轻量 Struts 仅有几个核心类要学习
开源 全部源代码在自由的 Apache 软件许可下,所有的选择都在你
强大的开发人员团体 有一个强大的开发人员团体使用Struts。邮件列表时非常活跃的。许多
开发人员的扩展是很成功的 强大的供应商团体 Struts 已经和其他一些产品合在一起,包括Jcorporate的s Expresso 和 IBM的 WebSphere。一些厂商也提供Struts专用工具。 强大的产品支持 Struts 有其自身的专业管理的JGuru 论坛。Struts邮件列表至少可以通
过两种支持门户进行访问。
Struts 已经被许多文章和书籍涉及,并有一些组织提供专业的教程
强大的开发团队 超过30个开发人员为Struts 1.1做贡献。Struts团队现在有九个活跃的志
愿者,他们全为源代码负责
稳定发布版本 Struts正式发布版本要经过长期的测试,并没有最后期限,所以团队可
以提供高质量的产品 i18n 支持 支持内建的国际化 高度兼容 Struts专注于提供公共标准100%兼容的产品 全方位的标记扩展 Struts包括一系列通用标记扩展。他们一起可以符合你所有的 JSP 需
要,而不用编写脚本程序
良好文档的源代码 Struts JavaDoc非常详细,以使你几乎不需要参考源代码。这其实是个
高级别的用户指南。 建立在设计模式之上 Struts 框架在其架构中实现了一些经典的设计模式,这些模式为许多开发人员所熟知。 可扩展性 所有默认的设置都可以配置。核心Struts可以被重写,和子类化。开发
人员可以定制关键类如ActionForm 和Action.
2.7 小结 今天的开发人员需要建立全特征的应用,并且可以随时维护。Web 应用框架,如 Struts,
些servlet 容器的兼容性测试。
truts 也构建于通用的设计模式,特别是 MVC 架构。框架鼓励应用采取分层设计。这种
决方案。它绝不会抑制你的应用,并有随处有一些免费资源
尽管有一些阻碍, Struts 也很容易地成为现今最流行的Web应用框架。
过头来运行Struts,并创建另一个应用。
解决了这个普遍问题,所以开发人员可以专注于它们应用的特定功能。在开发Web应用时,框架特别重要,因为HTTP 和 HTML 要创建动态应用非常困难。 Struts 使用了大多数标准的Java servlet API 并成为一S设计使应用具有强壮性和伸缩性。 架构的一个关键之处是它扩展了HTTP 请求-响应循环的流程。Struts 控制器管理着应用使用的路径,帮助安全的收集用户输入,并可以本地化应用消息,特别是错误消息。 Struts 是一个富有效率的解可以使用。 当然, Struts 还有一些缺陷。许多类名的选择在开发时显得比较轻率,容易引起混淆。其他一些地方也值得改进。
理解Struts 原理
使用Struts 控制流 讨论Struts 的优缺点
A common mistake that people make whencompletely foolproof is to un?框架,以及它能给你的应用开发所带来的好处。我们相信一旦你也构和设计,你就可以很好的在你的应用中使用架构有个充分的全面印象,我们将总体介绍响应事件循环的方式。只有彻底理解这个处理原理才能最好的在应用中使用这个框架。应该是个漫不经心的决定。很多人将使用这本书,特别是用是否适合它们的项目。因此, 对专业开发人员。为做出正确的决策,Struts
trying to design something
derestimate the ingenuity of
complete fools.
Douglas Adams, Mostly Harmless
2.1 Talking the talk
本章深入探讨Struts
能“随便谈谈 ”web架 Struts。
为了能对Struts Struts的控制流和它处理请
求-
选择一个web 应用框架不
这章的内容来评价Struts 我们在这章的最后将有一个关于Struts
优缺点的公正的看法,并阐明其总体性能。
Struts 设计针 专业人员应该知晓工具的能力和限
制性。
2.2 为什么我们需要
今天的web 应用基本上都是代表共同理念的关键组件。通常,开发团队需要在有限的
时间里创建应用,然它们不得不正确的构建,并能持续构建它。
Java web 开发人员已经有一些工具可用来建立表现层,比如JavaServer Pages 和
Velocity 模板。也有一些机制来处理数据库?如JDBC 和Enterprise JavaBeans (EJBs)。但我们
用什么来将它们集合在一起? 我们已经有了型材和砖墙…还缺什么?
2.2.1 退一进三
在上世纪80年代,当GUI被发明时,软件架构认为,应用具有3个主要部件:
管理数据的部件,创建屏幕和报表的部件,以及处理用户交互和子系统交互的部件
[Ooram]。
在90年代早期,ObjectWorks/Smalltalk 编程环境将这个3角结构引入为一个开发框架。
按Smalltalk 80的说法,数据系统称为模型 Model,表现系统称为视图 View, 而交互系统称为
控制器Controller.。许多现代开发环境,包括Java的Swing, 都使用Model/View/Controller
(MVC) 架构作为它们的基础架构 。
图 2-1 MVC架构 Java web 开发者已经有很多有用的工具,比如JDBC 和 JSP, 作为 Model 和 View的
2.2.2 进入 Struts
制器。Struts 控制器搭起了Model 和View之间的桥
梁。框架也包括开发人员想用来开发可伸缩的、先进的应用的其他组件。Struts是一个“隐
应用如何准确的和
用户进行交互。这些组件在逻辑名称后隐藏了令人讨厌的、繁琐的实现细节。开发人员可以
编 细节,然后转头考虑它们的应用应该做什么,而不是考虑应用应该如何
做。
据和其
手段,但作为控制器的工具和组件在哪? Struts 的核心是一个MVC风格的控藏支柱”的集合,帮助开发人员将分散的材料如数据库和页面,结合成一个整体的应用程序。2.2.3 Struts控制器组件 Struts 控制器组件是一个可编程的组件集,允许开发人员定义它们的一次性写这些实现 用户通过超链接和HTML form与Web应用程序进行交互。超链接引导页面显示数他内容,如文本和图像。表单通常通过一些定制动作向应用提交数据。 主要 Struts 组件
如图5中所示, Struts提供了开发人员可用来定义超链接,表单,和定制动作这些交互
的组件。我们已经使用这些组件在第1章创建了一个入门程序。第3章,我们还要用他们来创
建另一个程序。然后,在第4章,我们将讨论这些组件的详细配置。随后的章节,将详细讨
论如何将每个组件用在你的程序之中。在第4章,我们将展示如何在运行的程序上下文中使
用这些组件。但是,因为这章是架构性的总体介绍,所以我们继续介绍Struts的主要部件。
图 2-2
注
Struts 组件是通过一个XML 文件进行配置的。实践中,配置项是Struts 框架的有机组成部分。为了
将他们糅合在
2.2.3.1 超链
web页面,
或者是定制动作。 人员可以定义超链接为一个
ActionForward.
path 然后通过
名称来引用Acti
Struts启动时读入。 onForward列表。
可用来创建到欢迎页面链接的
一起,我们在讲述它们的时候,会展示每个组件的XML配置项。 接 对应用开发人员来说, 超链接是指向应用中某些资源的路径。它们可能是 它可以包含特殊的参数。在Struts中,开发。 这些对象都有个逻辑名称和一个path 属性。这使得开发人员可以设置onForward。ActionForward 通常在一个XML文件中定义,这个配置文件在Struts 使用 XML 定义来创建Struts 配置,包括一个ActiActionForward 对象的XML元素看起来可能像:
<forward
name="welcome" path="/pages/index.jsp"/>
这个元素创建一个 ActionForward JavaBean ,其name属性设置为welcome, path 属
标而不用改变所有引用该链接的组件。在大多数Web应用中,像这样的细节被硬编码到JSP
困难并且容易发生错误。在Struts 应用中,这些细节可以通过
应用配置来改变,而不用触及到具体的页面和Java 类。
难题留给了开发人员。Struts framework 提供了ActionForm 类, 它设计来处理从
修订循环的
性设置为/pages/index.jsp. JSP 页面和其它组件就可以引用welcome 转发。Struts 框架将查找welcome ActionForward bean 并检索path 属性来完成这个超链接。这时开发人员可以改变链接的目或 Java code中,使维护变得2.2.3.2 HTML表单 web 协议,HTTP 和 HTML,提供了一个从表单提交数据的机制,但却把数据接收作为一个HTML 表单来的输入,校验输入,重新显示表单以供用户进行修订(如果需要),以及伴随相应的提示和信息。ActionForm 其实是具有一些标准方法来管理校验和JavaBean。Struts 自动匹配JavaBean 属性和HTML 表单控件的属性。开发者定义ActionForm类,余下的就交给Struts 。 例如,这个类将自动用HTML表单中同名的属性来组装username域: public final class LogonForm extends ActionForm { private String username = null;
public String getUsername() { return (this.username); } public void setUsername(String username) { this.username = username; }
}
其它属性也会根据表单中的每个域被自动加入。们想要的属性。所以,完全不需要详细分析HTTP 请求。 ActionForm 是按通常的Java 类创建的。Struts配置通过一系列描述符引用A
这使其它组件可以从标准的JavaBean取得它
ctionForm
: <form-beans> 和 <form-bean> 元素。<form-bean> 元素是框架用来识别和实
ionF 的描述符:
类例化Actorm 对象
<form-bean name="articleForm" type="org.apache.artimus.struts.Form"/>
Struts 配置列出它使用的ActionForm bean的清单,并给每个bean一个在应用中被引用时的逻辑名。 1.0 和 1.1
Struts 1.1 中,ActionForm 可以使用Map (java.util.Map) 来存储属性名,而不是单独定义它们。
一种新的JavaBean, DynaBean, 可以在Struts 1.1 和后来的版本中使用。
你可以使用XML 元素来标识DynaActionForm 的属性。这使你可以使用 Struts 配置文件来定义
ActionForms。 2.2.3.3 定制动作
HTML 表单使用 action 参数来告诉浏览器将数据送到哪里? Struts 框架提供相应
的Action 类来接收数据。框架会自动创建、组装、校验和最后处理Action 对象对应的
ctionForm。这样,Action 就可以直接从ActionForm bean取得它需要的数据。比如下例:
A public final class LogonAction extends Action {
public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { MyForm myForm = (MyForm) form;
// ...
return mapping.findForward("continue"); } } Action 根据返回到控制器的ActionForward 对象作出控制流的决定。这允许Action 选
为保证扩展性,控制器也传递当前的请求和响应对象。实际上, Action 可以做所有Java
可以做的事情。
择一个逻辑名称,象continue 或者 cancel,而不是系统路径。 Servlet 1.0 vs 1.1 在Struts 1.1 中,新的 execute 方法应该是首选,而不是我们例子中的perform 方法。perform
已经不被推荐,但还保持向后兼容,予以支持。execute 方法体允许更好的例外处理。新的
ExceptionHandler 在第9章讲述。 关于Action 对象的详细信息,见第8 章。
onForm,和 Action 对象,Struts控制器层还提供几个特殊的组件,
包括ActionMappings 和 ActionServlet。 Struts 也提供在控制器层的应用本地化。
2.2.3.4 ActionMappings
来进行引用。 资源包括HTML 页面,JSP 页
URI, 或者说路径,Struts 框架提供了一个
ActionMapping 对象。 象ActionForward 和 ActionForm一样, ActionaMapping通常也在
L配置文件中定义:
除了ActionForward, Acti 在一个web 应用中,每个资源必须通过URI面,和定制动作。为了给定制动作一个XM
<action-mappings>
<action
path="/logonSubmit"
type="app.LogonAction"
name="logonForm" scope="request" validate="true" input="/pages/logon.jsp"/> </action-mappings> 这也允许同一个Action 对象定义为不同的ActionMappings。例如, 一个映射要求校验
而另一个映射不要求校验。
ervlet
虽然它也可以子类化,
但大多数Struts 1.0 的开发人员将ActionServlet 处理为一个黑盒:他们只是配置它,然后让
自己工作。
在Struts 1.1中,ActionServlet 是比较易于扩展的。第9 章将讨论Struts 1.1 ActionServlet
的扩展点和配置选项。
Web 应用也通过各种提示和信息与用户进行交互。Struts 组件均有内建的本地化特征,
以便Struts应用可以为国际化用户使用。我们在此书中贯穿使用本地化特征。本地化的详细
讨论见第13章。
Form,定制的服务器端动作定义为Action 类。
需要访问JDBC和EJB的开发人员也可通过Action对象进行。这样,表现层不需要和Model
2.2.3.5 ActionS Struts ActionServlet 完全在幕后工作,它将其他组件绑定在一起。它 新2.2.3.6 本地化 2.2.4 用Struts开发Web应用 要使用Struts开发web 应用,开发人员将需要的超链接定义为ActionForward,HTML 表单定义为Action
层打交道truts Actio 。S n 对象将收集View 需要的数据,然后将它们转发到表现页面。Struts
JSP 页面一起使用,简化 提供 JSP 标记库,它们和 HTML 表单和存取Action 要转发的其它数据。其它表现机制,比如Velocity templates, 也可用来访问 Struts 框架,来创建动态的web 页面。这种处理流程入下图: 传给视图
第10章和第11章学习如何创建
Struts的表现页面。
架构前,让我们看看一个Web应用框架必须说明的问题。
2.3 为什么需要框架
论了为什么框架很重要。但为了真正理解一个解
决方案,我们需要了解问题所在。为web开发应用虽然是值得的,但也要迎接各种挑战。让
挑战。
2.3.1 Web? 永无休止的修补
Web 开发者受到两种web缺陷的影响。首先,我们希望使用浏览器作为客户端。其次,
必须使用web协议进行通讯。
Web 浏览器通过HTTP协议通信,并用HTML显示页面。Web浏览器发送HTTP请求,
加工和显示它收到的响应。在处理很少改变的预先编好的页面时,这是个很好的平台。但
我们大多都是编写动态程序,页面针对不同的用户是不同的。虽然有一些现成的动态特征的
段,web 仍然受到HTTP/HTML 的制约。
如下表所示: web 协议和客户端的限制,确定了如何编写Web程序。
表格 2-1 HTTP/HTML 的限制
图 2-3 数据回 关于和Struts中如何使用各种数据系统,见第14章。 在深入Struts 第1章,我们介绍了应用框架,简短讨我们快速看看是什么使web 开发富有我们并手限制 导致的困难 协议 缺省情况下,HTTP接收来自于网络上各种客户端的连接。但各种服
务器间的行为是不一样的; 首先,HTTP用简单的文本域来传输数据。传输二进制文件需要复杂
的协议扩展
HTTP协议是无状态的,需要额外的努力来跟踪程序的用户
HTTP信赖并期望客户能提供正确的信息 客户端 浏览器是个独立的程序,处于应用的控制之外
所有的浏览器都是不一样的,都只支持官方标准的一个子集
从浏览器的输入可能是不正确或者不完整的。甚至可能是敌意的,
和对程序有害的信息
HTML不能够建立一些在桌面环境中有的接口元素
用缺省数据建立HTML控件对应用来说是个考验 很不幸,这种状况现在并没有些许改变。Web开发人员在想战胜挑战时必须看到这些缺
对编写强壮的Web应用有太多障碍,使用框架便显得至关重要,免得你的应用陷入
无休止的工作和改进之中。
我们面临的挑战是很巨大的。但同时也是值得的。HTTP 协议和
HTML 客户端使所有的人都可以访问你的应用。没有其他哪个平台能声称这样。
解决方案
,Java Servlet 平台[Sun, JST] 扮演了一个基本框架,为Java web 应用提
供了大量的能力。Servlet 提供了一个处理HTTP请求和确保响应的基本接口。它在HTTP之
话” 上下文,帮助跟踪应用程序的用户。当然它也提供其他的上下文,帮
助应用传输数据到浏览器或者应用中的其他servlet。Java web 应用也具有对基本安全特性的
不同的服务器上的管理是不一样的。
为了将这些内容集成在一起,Servlet规范引入了一个容器来管理它们。容器也可以提供
其他服务,比如作为一个JSP的处理器。Servlet 容器可以包含它自己的web server,也可以
对数据库访问, Java 应用在其建议中有另外一个通用的框架: JDBC。开发者可以写
准的SQL 接口,而将烦人的细节留给适配器来处理。这使得可以很容易的改变数据库厂
都可以和EJB一起使用。
总之,这使得基于Servlet的web应用非常轻便,并相对易于编写和维护。Servlet 和 JSP
角色。 象Strtus这样的Java web 应用框架构架于Servlet之
框架也包括一个类结构树,这些类你可以在
中实 扩展。通常, 应用框架的目标是帮助你将你需要的数据从浏览器发出,
它们既不阻碍数据库访问,也没有提供帮助。而某些框架, 如
s 库访问,而将其它任务留给开发人员或者其他框架。
2.3.3.1 通用框架策略
陷。因为 在开发Web应用时2.3.2 Servlet 如第一章所述上构建了一个“会统一访问,而这些安全特性在简单的作为一个现存服务器的附属组件。 标商,而不用重写源代码。 为了取得远程服务器的高性能数据库访问, web 开发人员可以使用EJB平台。大多数ava 应用框架,包括Struts, J 在编写应用中扮演了完全不同的上,给开发者提供一个无缝的集成环境。 2.3.3 Servlet 框架 大多数,不是全部, Java web 框架使用 Sun Servlet 平台为基础。这些框架都绑定一些预制的servlet,你可以插入到你的应用中去。你的应用现或者进入到编程结构之中,这样你的应用就可以使用它?或者从编程结构中发出,进入到浏览器之中,这样你就可以看到。 一些框架,如 Turbine [ASF, Turbine],也提供helper 类来运行于 JDBC 数据库。其他框架, 如Struts, 则是模型中立的。dbForm [dbForms],则专注于数据
如下图所示, Java web应用框架使用一些通用技术来帮助产品易于设计、编写和维护,
式(Front
外部表现系统
让不同的人同时工作在同一应 a工程师可以工作在和中心控制
相关的类,而页面设计者则专注于JSP。除了JSP,其他表现系统,如Velocity Templates 或
X
些书象 Design
Patterns [Go4] 和 Core J2EE Patterns [Go3]给出的范例中根深蒂固了。许多开发者在讨论并
些 第一次在Web环境中实现它们。使用设计模式,如MVC,使
容 情来构建你的应用。在桌面环境中使用设计模式的优点已经众
所周知了,但在Web环境部署这些模式却对大多数开发者来说还是不确定的。
包括: 外部配置文件 提供开发人员不想嵌入源代码中的实现细节。 中心控制器 提供一种方式,将HTTP 请求排入一个易于管理的队列。这种设计有时叫前端控制器模 Controller [Go3]) 用的不同部分。如, Jav器者LST, 都可以和Struts一起使用。 框架通常有各种组件,但基本上都共享这个特性。这些公共策略早已在一使用这模式,但也许还没有你可以易的通过做正确的事 图 2-4 通常使用配置文件,控制器和表现系统的框架 2.3.4 黑盒-白盒统一体 框架有时分为两极标有白盒和黑盒的统一体[Fayad]。白盒框架严重依赖于面向对象的
语言的 承和动态绑定。黑盒框架则注重定义可插入组件的接口,然后基于这些接
口提供基本的起始组件。接口和基本组件通常提供热点(hotspot )方法,这个方法可以直接
使用或者重写后提供特别的行为。
特征,如继
定义
热点有时也称为是灵活点或者扩展点,它其实是框架中的一些位置,在这里可以加入一些代码来定制框架。热
点(热点 应用中可 系统)每个以被框架所支持的不同特征。本质上,它们代表框架所解决的问题。许多面向对象
框架有一个核心系统和一些热点子系统组成[Braga, et al] 像许多正在使用的框架, Struts 使用混合的黑盒和白盒技术。但总体上,框架将偏向
统一体的黑盒一端。
黑盒框架通常依赖于设计模式。Struts 也不例外。事实上,设计模式通常被用来作为框
架的总体描述 [Johnson
在Struts 框架之中。
2.4 Struts, Model 2, 以及 MVC
Struts 关于自己要说的第一句话就是:框架
… 鼓励应用架构基于Model 2 方法,即经典的MV 设计模式的变体
这句话打消了一些web 开发
惑了。 事实上,没有深入了解MVC 和Sun Model 2,要理解很多Struts的文章都很困难。
2.4.1 MVC 的演化
如2.1节所说, Model/View/Controller原本是建立Sm 应用的框架。框架支持代表
应用状态、屏幕表现和控制流的3个类,分别叫做 Model, View, 和 Controller。
]。为保持这个趋势,我们先介绍一下设计模式,以及它们是如何用C 者的疑虑,对那些还没深入Model 2 或 MVC的人来说却更加疑alltalk nts of R
图 2-5 MVC 三角
Smalltalk MVC 框架 在流行的书Design Patterns: Eleme eusable Object-Oriented
Software[Go4]是作为案例来研究的。Design Patterns 这本书有四个作者,被称为“四人帮
GoF”。
Design atterns中的MVC 例子称赞 通知/ 订阅者(notify/subscribe )协议和观察者
Observer模式的使用。例子的基础是,对同一数据,系统可能需要不同的显示视图,比如条
形图、饼图、数据表格等等。这是一个划分应用的精彩理由,经常被重复引用。
P
图 2-6 The Model data can be used in several d如果ferent views. 在图2-6所示的例子中,每种视图可能在同一时间显示给不同的用户。应用必须保证在
最近的模型改变状态。
以应用它其他平台上面。
贝粘贴”。
t
HTML的任务。在例行课程中,结合使用 JSP
t 开 l 2 (单独使用JSP称为Model 1)。
iew-Controller 架构。
在很多场合,现在交互使用Model 2 和 MVC这两个词已经很平常了,虽然还有一些争
MVC,以及是否支持经典的观察者通知模式。没有观察者通知的
od C。.
认为区别于MVC 的一个原因是,观察者/通知模式不能在web 环境内工作
其下面的数据或者模型改变时视图的更新。为改变模型,用户提交一个请求给控制器,由控制起来配合改变模型。数据视图必须跟着改变,以反映 Smalltalk MVC 方案使用观察者通知模式。在这种模式下,每个视图注册为一个模型数据的观察者。然后模型可以通过发送消息给所有这册观察者,通知它们相关的改变。其为 Smalltalk MVC 框架已经通用化了,他也可2.4.2 Model 2的出现 JSP的意图是使创建动态页面更容易。JSP 首先是作为servlet的替代引入的,还有就是MS的ASP。Servlet的强大功能当作易于创建服务器页面的工具提供给开发者。但强大的功能伴随着巨大的责任。很多团队发现,如果他们一不小心,他们的项目就会因为纠缠如麻的页面变的容易崩溃。进一步的特性需要使用复杂的脚本程序。但脚本程序是非常难于重用的?除非你在页面间把代码“拷 工具页面也可以包括进来,但他们很难被组织在一起,并且造成非常丑陋的“资源”树。有些东西会出错。 很多开发人员很快意识到, JSPs 和 servlets 可以一起使用来部署web 应用。Servle可以应付控制流,而 JSP则可专注于讨厌的编写和 servle始被称为Mode 当然,从Sun哪里仍然没什么新东西... 而且很多人很快指出 JSP Model 2 类似于经典的Model-V 论,即一个应用是否是Mel-View-Controller 有时被称为MVC2 或Web MV2.4.3 应用层?和视图去耦合 Model 2 被的很好。HTTP 是一个 “拉” 的协议: 客户请求然后服务器响应。没有请求就没有相应。观
察者模式需要一种“推”协议来进行通知,以便服务器能在模型改变时将信息推送到客户端。虽然也有一些方法能模拟将数据推送到客户端,但这和基本情况相悖,并且会视为是权宜的
补。 修 被表示为:一个互相连接的三角形。在
应用中维护范式中的“通知改变”部分是非常困难的。
这些东西在所有资源都在一台服务器上,而且客户端保持一个开放连接的情况下工作得
常
包括web应用,在视图进行状态查询的概念时退缩了。绝大多数
况
引入层模式将状态改变和状态查询的职责加于控制器之上,并伴随
着改变通知。
图 2-7 MVC 通常表示为3个互相连接的组件 图2-7是典型的Model-View-Controller范式,经常web 非好。如果资源分布在不同的服务器上,并且客户端不能维护一个开放的连接情况下,工作的并不理想。 许多分布式系统架构, 情下,远程应用是按层模式[POSA]设计的。基本上,层模式下,层内的对象可以和同一层或者相邻层的对象进行通信。在一个复杂应用中,这可以在添加组件时,防止依赖关系呈指数增长。在设计远程应用时,分层是一个核心模式。 从MVC 上下文中,
图 2-8 Web 应用的层模式
` 如图2-8 ,分层的web 应用使用一种比传统MVC模式更加“扁平”的模式。控制器被
必须通过
控制器。另一个改变是, 它使用从控制器传递的
数据而不是直接来自于模型层。 ,允许控制器选择数
据和显示这些数据的视图。
2.4.4 Struts 如何实现
Struts 通过提 这个控制器可以用来管
理JSP页面和 和ActionMapping来保
证表现层之外的控制流决策来实现 引用一个逻辑目标。控制器组
件在运行是提供准确的URI。
夹在表现层(View) 和 应用逻辑 (Model)之间。 每个组件的主要职责并没有改变。流程有轻微改变,即查询状态和改变通知都当视图,或者表现层需要加工动态页面时,这种改变去除了View 和 Model的耦合 Model 2, MVC, 和层 供一个控制器Servlet实现了Sun的 Model 2 架构,其他表现设备之间的流程。Struts 通过使用ActionForward MVC/层 模式。JSP可以表列出了Struts的核心类,即对应的经典的MVC组件职责。 表格 2-2 核心 Struts 类和MVC的对应 类 描述
ActionForward 用户指向或者视图选择
ActionForm 状态改变的数据 ActionMapping 状态改变事件 ActionServlet 控制器,接受用户请求和状态改变,以及发出视图选择 Action
控制器的一部分,于模型交互,执行状态改变或状态查询,以及告诉
ActionServlet 下一个选择的视图 除了这些核心类, Struts 使用一些配置文件和视图助手(view helpers)来沟通控制器和模型。下表列出了Struts 配置文件和描述了他们在架构中的角色。 表格 2-3 Strtuts配置文件 文件 目的 ApplicationResources.properties 存储本地化信息和标签,以使应用可以国际化 struts-config.xml 存储控制器对象的缺省配置,包括模型支持的用户指向,状态改变,状态查询 为将Struts配置数据暴露给视图,框架以JSP标签的形式提供了大量的助手类,如表: 表格 2-4 Strtus视图助手 标记库描述符 目的 struts-html.tld 扩展HTML Form的JSP标记 struts-bean.tld 扩展处理JavaBean的JSP标记
sts-logic.tld rut 扩展测试属性值的JSP标记 将以上内容放在一起,下表按层列出了Struts 组件: 表格 2-5 Struts 组件,按层索引 视图层 控制器层 模型层 JSP 标签扩展
ActionForwards
ActionForm classes
ActionMappings
ActionServlet
Action classes ActionErrors MessageResources
GenericDataSource
JSP, Velocity 模板, 以及其他表现系统 各种工具类, 比如CommonsDigester和
CommonsBeanUtil 开发者提 供 的其他数 据 服务和
API 注,根据层模式 ( 2.4.3), 组件应该只能和相同层和相邻层的组件交互。因此, Model 组件不能直接和View组件进行交互。 意
先认识这片森林。你读完此书后,我们建议你再次回来,看看每一部分是如何切合
这个总图的。
2.5.1 总图
实践中,控制器与视图的交互通过请求,会话以及Servlet平台提供的应用上下文进行。 (2.3.2)。 控制器和模型的交互通过文件和存储系统完成 (比如装入XML文档或者属性文件),或者通过其他服务,如TCP, 创建一个到JDBC数据库的连接。 2.5 Struts 控制流 因为web 应用是动态的,所以很难表现“One True Control Flow” 。依赖于环境,不同的方式下有很多不同的事情发生?特别是在web 应用中。但是事情仍然有一个通用的秩序。 如果你是个Struts,应用框架,甚至web 应用的新手,这些流程刚开始可能难以跟得上(理解)。亟待解决的各种问题不一定那么明显。我们将在本书中详细涉及。首先,在介绍树木之前我们进
-响应流
图 2-9 Struts 请求-相应流程 图2-9以UML以次序图的方式展示了Struts 请求-响应流程。我们来按这个请求程走一遍。 括号内的数字请参照图11中的相关地方: 客户请求匹配Action URI 样式的路径 (1). 容器将请求传递给ActionServlet. 如果这个是模块化应用,ActionServlet 选择响应的模块。 ActionServlet 查询路径的映射。 如果映射标明了一个form bean,ActionServlet 看是否已经有一个实例,或者创建一
个新的实例 (1.1)。如果已经有一个form bean,ActionServlet 重设它,并根据HTTP请求重新组装它。 如果 mapping 的 validate 属性设置为 true, 它将调用 form bean 的validate 方法(1.2)。 如果失败,Servlet 将控制转发到input 属性标明的路径,控制流终止。
如果mapping 标明一个Action 类型,如果它已经存在或已经实例化,它将被重用(1.3)。 Action的perform 或 execute 方法被调用,并传递一个实例化的form bean (或者 null)。 Action 可以组装form bean, 调用业务对象,以及其他需要做的事情。 (1.3.1-1.3.4)。 Action 返回一个ActionForward 给ActionServlet (1.3.5).
如果ActionForward 指向另一个 Action URI,重新开始; 否则,显示页面或者其他
资源,流程结束。通常,结果是一个JSP页面,或者Jasper, 或其它类似技术 (非 Struts)
加工的页面。 (2, 3).
如果JSP 使用Struts HTML 标记, 并且在请求中看到正确的ActionForm (1.1),他们
会从ActionForm中组装HTML控件。否则, <html:form> 标记将创建一个。从
Struts 1.1开始, 如果form 标记自行创建一个ActionForm ,它将调用ActionForm的
Reset方法。如果你只是想创建一个空白的表单 (1.1),你可以使用标准的ForwardAction(见第 8章) 来通过Action传递控制,然后离开页面。 2.5.2 出色的细节 他们说,恶魔藏在最隐秘的地方。 前面章节的大纲和图示很好的显示了Struts的概揽,但忽略了重要的细节。让我们更深
入到更好的地方。因为这里是HT 始。
servlet mapping。 容器使用这个设定来决定哪个请求将被送
到哪个servlet:
TP, 所有东西都是从请求开2.5.2.1 请求由容器接收 Struts 框架的核心组件是 ActionServlet。象所有的servlets, 它生存在容器中, 比如Tomcat, Resin, 或者 WebLogic等。当容器启动时,读入部署描述符 (web.xml),告诉容器要装入哪些个servlet。 一个标准的servlet 设定是<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/do/*</url-pattern> </servlet-mapping> 这里,我们让容器将ActionServlet映射到那些符合/do/*样式的请求。这些请求可以是:
/do/This
/do/That
/do/somethin hatever.
许多应用喜欢使用前缀:
g/W
<servlet-mapping> <servlet-name>action</servlet-name>
<url-pa -pattern> ttern>*.do</url
</servlet-mapping>
URL 样 以使用象th
何有效的扩展名,但.do 是比较简单和常用的选
当一个请求随着符合Servlet上下文的路径组件提交时,容器将其转发给ActionServlet。
可以有其他的servlet
来处理其他格式的请求路径。不 求将直接送给容器默认的web
server。
2.5.2.2 请求被ActionServlet 接收
ing, form bean, 最
式也可is.do 或 that.do 或 /something/whatever.do的样式。可以用任择。 不匹配的请求则不转发到ActionServlet。比如,匹配*.jsp的请求将直接转发给容器的 JSP 服务,比如Jasper(如果你使用Tomcat 或者WebSphere的话)。在应用中匹配所有servlet mapping 的请 当ActionServlet 收到一个请求, 它通过一系列的流程处理locale, mapp
后是Action来运行这个请求。这里某些步骤只在Struts 1.1 应用才有:
处理多部分请求. 如果请
Servlet 用一个特殊的句柄包装这个请求,避免处理错误。
求是个多部分请求 (比如,一个表单加上一个MIME附件), 处理路径 ActionServlet 首先检查这个请求路径是否是一个应用模块。如果是,相
应模块的配置被选中。[Struts 1.1]
处理场所. 默认下,Ac 标准的locale 对象在用户会话
的上下文当中。如果没有, ActionServlet将放入一个。这个对象将为每个用户提供
化表现。
tionServlet 会检查是否有一个本地
处理内容和不缓存 默认的MIME 类型和可选的请求头将加在响应之上。
处理映射( Mapping pping,是否有注册的路径符合
正处理的请求。如果没找到, ActionServlet 转发到默认(或 “unknown”) Action(如
有默认或未知A ad request” 错。如果找到相关映
射,将被放入请求之中,供后面引用。
) ActionServlet检查ActionMa果设定ction),否则,产生一个 “b 处理角色. ActionServ 可以访问action. [Struts 1.1] let 检查是否用户被授权
处理ActionForm. ActionServlet 检查是否mapping 标明一个ActionForm.。如果是,
之内(默认是会话)。如果不存在,
ActionServlet 创建一
servlet 检查是否已经有一个存在于特定的范围个。 处理组装. ActionForm的 reset 方法被调用,然后通过反射机制被自动组装。匹
配 orm属性的参数将被使用。其他参数和属性被忽略。 ActionF
处理验证 ActionForm的 validate 方法被调用。如果方法返回false, 控制传递给
ActionMapping的input 属性 ction 未被处理。 标明的路径, A
处理转发和包含 如果ActionMapping 标明 或include 属性,控制被传
递给其他资源。否则ActionS 给一个Action 对象。
forward ervlet 将请求委托
处理 Action. 如果mapping 标 型, ActionServlet检查是否已经有一
个被实例化了。如果没发现, Action 对象将被实例化。每个类只能有一个Action 对
模式),它通过多线程处理所有对它的请求。
perform 或 execute 方法,传递请求, 响应, mapping, 以及form bean。
Action 执行要求的行为,可以包括:
明一个Action 类象 (SingletonServlet调用 Action的
访问数据系统,比如JDBC 数据库 在请求中创建被视图使用的对象
如果需要,在会话中创建对象
根据需要更新会话对象,比如用户的场所
执行需要的业务功能
处 其他错误条 理以外和件 发送一个直接发送一个响应,或者返回一个ActionForward 给servlet
务,可以放在业务对象中的代码都应该放入业务对象。
ction 是一个控制器类,不应该用来处理业务的核心逻辑。
Action 返回ActionForward
ctionForward ,重定向或者转
这里某些行为,象访问数据库,通常由Action 调用的业务对象来处理( Business Delegate 模式)。 Action 处理一些web特定的任A2.5.2.3 Action完成后,它返回一个ActionForward。如果 ActionForward 为null, ActionServlet 假定响应产生了,但不做任何事情。否则, ActionServlet读入 A
发请求到相应的资源。 如果请求是另一个Action URI, 容器将请求返回给ActionServlet。否则容器发送请求到其
它servlet或service。
展用来编写页面的动态部分。有时,也使用JSP模板,以便页面可以从其
它组件进行构建。
数据在JavaBean中传递到请求上下文中的页面。这就是熟知的视图助手
(View Helper )模式 [Go3]。 标签扩展简单的调用JavaBeans的方法,并返回格式化的数
如果ActionForward 设为重定向(redirect), 请求被发送回客户端,并提示重新提交一个新请求到特定的地址。 2.5.2.4 由Jasper (或类似的东西) 加工JSP页面 ActionServlet 发送一个请求 到 JSP, 请求是被另外的服务处理, 如 Jasper。典型地, Struts和其他标签扩 通常, 动态据。而数据如何被放入页面中那是表现逻辑的事情。数据本身的格式通常是业务逻辑的一部分,所以委托给了bean。 Struts 标记也可以访问框架提供的视图助手。这些包括本地化标签和提示,错误信息,以及超链接路径。另外,Struts 标记可以计算表达式,通过列表反复,以及在HTML表单中组装控件。 2.5.2.5 其他 servlet 加工响应 处理完Action后,请求可以被送到应用中的其他 servlet或服务。其他表现系统,如 Velocity templates, 可以通过servlet 上下文访问框架资源。 2.5.3 Struts 是富有效率的吗? 详细描述完Struts处理流程后,你可能会想知道这些的花多长时间。通常,Struts应该能提升大部分正确设计的Web应用的性能。在本节中,我们检查一些关系到框架效率的特殊设计点。 定义 Performant 是一个法语词,意思是有效率(efficient)。软件工程常用这词来表示一个流程或者设备在实际中执行得很好。 Struts 不仅是线程安全(thread- d-dependent )的。
线程化。这种核心策略节省了资源,
并提 最 用一个单独的Action来路由各种相关操
作来 挥
Acti 类层次.
ru
用户不得
资源是有限的,并允许它们更好的使用。
Struts 标
ru 至消除
safe)而且是线程依赖(threa Struts使用轻量的Action 对象,而不是各个单独的servlet,来对请求处理响应。 Struts 实例化每个Action类一次,并允许其他请求通过原有的对象供大的吞吐性。一个正确设计的应用将通过使发这种特征。 onForm bean最小化子类代码并缩短子Stts 框架的一个关键点是可以从请求中自动组装ActionForm bean 。没有这个组件, 不自行编写代码并实例化来组装每个bean类。小心使用反射机制会节省不少资源,签库提供通用功能 Stts一起提供的bean 和 logic 标记库符合大部分JSP 标记的需要。它们减少甚
了编 额
的标签来的有效率。
Struts 组 用来说都是可重用的.
这个方法用来从 组
装一个F
Struts 本 余JSP.
个单独的
Struts 设
Stru 。这使得开发
人员可以扩展存在的类而不是重新编写新类。而且,Struts 也和应用共享资源。这时开发人
使 ,而不用编写和实例化它们自己的类。
标准兼容
好的文档.
有对后端模型做任何假定,一个应用可以按其最有效率的方式实现模型层。
Struts Actions 可以调用一系列助手类来访问需要的数据。一旦数据被检索到, 对JavaBean
易保持值对象,这样来减少了大量的模型层调用。
2.6 Struts 的长处和弱点
一样, Struts 是个解决方案包。它也有其长处和弱点。这里的某些观
点具有主观性,但也希望能对你有些帮助。
.6.1 弱点
已
ease中解决。下表列出了Struts 1.0 的弱点,并在Struts 1.1种解决了。如果你
过Struts,这里某些问题是很精彩的,现在Struts 1.1可以更加符合你的要求。
-6 Struts 1.0 的弱点,在 Struts 1.1 中解决了
写外标签的需要。JSP 规范在JSP重用标签 。使用相同的通用标签3次比使用3次不同件对应框架绑定的工具可以在大部分应用中使用。 BeanUtil.populate 方法就是个例子。HTTP请求组装一个ActionForm Bean,但也可以用来从其它类型的映射中ormBean。重用组件可以减少开销和节省资源。 地化策略减少了大量冗通过允许本地化页面在运行时才获取,国际化应用可以为每种可能需要的语言只提供一页面。同时,相同的消息系统也可以用于处理错误信息。同一对象提供了双重用途。计为一个开放架构. ts 组件设计来是可以被应用子类化的,以便可以提供其它的服务功能员可以用存在的组件Struts是轻量型架构. 类似的框架也许提供数百个类和几十个包。整个Struts 框架 由5个标记库和5个核心包组成。 Struts是的t. Strtus在许多运行标准组件的容器上都工作的非常之好。 Struts是开源的,具良 这意味着开发人员可以检查源代码,找出一些潜在的瓶颈。而且Struts是模型中立的。因为Struts 并没的依赖,使Struts更容 象一些复杂系统2 不管有多么喜爱Struts,重要的是看到框架是干什么的,它的瑕疵和所有。有些弱点经在Struts 1.1 rel以前层使用表格 2弱点 说明
Logging(记录) Struts 使用容器的缺省记录系统,没有提供一个自己的记录包来
为应用提供记录机制。
(Struts 1.1 实现了 Commons-Logging 接口包)
每个应用装入一个单独的配置文件 大型项目可能需要使用多个不被整个团队共享的配置文件
(Struts 1.1 支持多配置文件)
每个场所装入一个单独的资源文件 大型项目可能需要使用多个不在整个团队共享的资源文件。
(Struts 1.1 支持多资源文件)
没有服务管理器 ActionServlet 必须被子类化来提供附加服务,比如用户记录器或
者身份认证系统
(Struts 1.1 提供一些新的扩展点和组件)
ActionForm red tape Struts 1.0 希望开发人员创建定制JavaBeans 与HTML 输入表单
一起使用
(Struts 1.1 支持 Map和 DynaBean 来代替定制JavaBean.)
表2-6列出了框架当前的弱点。在下一节,我们将详细的讨论它们,并象资产一样描述。“Goofus” 或者 “Gallant,” 选择在你。 表格 2-7 Struts1.1的弱点 弱点 说明 没有事件模型 Struts 紧密和HTTP的请求-响应模型结合,这限制了开发人员更好地处理事件 调试 不支持自动调试(除错),开发人员不得不手工创建“断点”,
并向容器的记录系统写标准输出
没有缺省的数据模型或者具体的推荐 访问持久数据模型留给了开发人员 单一ActionServlet 一个应用终止可以使用一个单一的ActionServlet,这个限制可能导致配置冲突 需要理解Struts组件 开发人员需要理解一些特殊的类以及他们如何交互。 不能 优 提供先技术支持 ASF是个志愿者组织,没有全职人员提供可担保的响应 Mailing list已经成为知识的障碍 Struts 有一个日益增长的邮件列表,但要在其中找到最好的间以
非常困难。
正式 版 发布本并不快速 Struts正式发布版相对于其他项目来说先得慢了。开发人员必须经常检查“每日构件”或的最新改进。 i18n 限制 Struts 的消息资源对建立国际化的资源和错误信息非擦好,但不
适合于处理大文本块 JSP mindset 因为使用MVC架构, 使得资源对所有表现层都是有效的。这是个
长期的弊病对JSP来说。
JSP意外本地化 很多系统级消息,象JSP意外,都没有本地化,通常显示为英语
标记 冗 属性长 许多标记扩展要求很多参数,对编程来说很笨 perform 和 execute 方法体 Struts 架构的关键是将请求委托给一个 Action类或者叫分发者
dispatcher。Action 类是Struts支持的唯一分发者,并仅通过其
perform 方法来调用。这将应用限制在只能和perform 方法传递的数据一起工作。即使有办法超出这个限制, perform 方法也
是个瓶颈。 一个通常的请求要求ActionServlet组装几个ActionForm。但是因为 perform 接受单个ActionForm 参数,如果不经过较大的框架
革新是不可行的。 Struts 1.1 添加了一个execute方法,它有助于改善perform的其他
主要缺陷:因为他返回意外。然而,主要的问题已就存在。
模糊的术语 Struts 框架在明显的增长。而给一些应用选项和
类的名称却容易让人混淆。例如,web.xml “ 中的validate” 选项
却和Action 对象的validate 方法无关,而和如何解析配置文件相
关。同样,神秘的 “ null”
选项则表示当消息关键字未找到时,是否返回一个错误信息。
有个趋势是在类层次树种使用复合名称。在Action包中的每个类
都有个前缀为 “ Action,”这却是多余和容易混淆的。同时,在
Struts配置文件中, ActionMappings 定义的元素名是
“ Action” 而不是“ ActionMapping” 。如果开发人员引用一个 “ action,” 很难区别它们是指Action 类或是配置类的ActionMapping。 在 Struts 配置中, “ name” 域标识ActionForward 和
ActionForms“ path” 域标识 ActionMapping。“action-mapping
元素的 name” 属性则指出使用哪个ActionForm 。 ActionForward 的URI域也称为 “ path”,但可以包括伴随path
的查询组件。到ActionMapping 的 “ path” 不包括servlet 样式,
象 *.do, 但是ActionForward 的path 却包括 *.do 扩展名。 应用资源其实是真正的消息资源。
等等。 凡此种种,这些小矛盾可以把一些新手搞糊涂,并且使框架难以
学习 2.6.2 Struts的强项 强 项 说明 以HTTP为中心 Struts设计围绕标准 HTTP 请求-响应模式,为许多Web开发人员所熟悉 标准记录 Struts 可以使用容器的缺省记录系统,而不需要配置和理解其他包
可选的调试记录 Struts 可选记录大量状态处理时的信息,它们可以有助于进行调试 模型中立 Struts 并不倾向于哪个特定的持久层 在一个中心配置中汇集实现细节 Struts 配置封装了应用,或者应用模块[Struts 1.1]的实现细节。所以它
们可以作为一个整体评价和管理
允许为每个场所配置不同的消息
资 源
不同的语言翻译可以工作在他们自己的消息资源文件版本上。添加一个
新场所的支持仅需简单地添加一个资源文件 轻量 Struts 仅有几个核心类要学习
开源 全部源代码在自由的 Apache 软件许可下,所有的选择都在你
强大的开发人员团体 有一个强大的开发人员团体使用Struts。邮件列表时非常活跃的。许多
开发人员的扩展是很成功的 强大的供应商团体 Struts 已经和其他一些产品合在一起,包括Jcorporate的s Expresso 和 IBM的 WebSphere。一些厂商也提供Struts专用工具。 强大的产品支持 Struts 有其自身的专业管理的JGuru 论坛。Struts邮件列表至少可以通
过两种支持门户进行访问。
Struts 已经被许多文章和书籍涉及,并有一些组织提供专业的教程
强大的开发团队 超过30个开发人员为Struts 1.1做贡献。Struts团队现在有九个活跃的志
愿者,他们全为源代码负责
稳定发布版本 Struts正式发布版本要经过长期的测试,并没有最后期限,所以团队可
以提供高质量的产品 i18n 支持 支持内建的国际化 高度兼容 Struts专注于提供公共标准100%兼容的产品 全方位的标记扩展 Struts包括一系列通用标记扩展。他们一起可以符合你所有的 JSP 需
要,而不用编写脚本程序
良好文档的源代码 Struts JavaDoc非常详细,以使你几乎不需要参考源代码。这其实是个
高级别的用户指南。 建立在设计模式之上 Struts 框架在其架构中实现了一些经典的设计模式,这些模式为许多开发人员所熟知。 可扩展性 所有默认的设置都可以配置。核心Struts可以被重写,和子类化。开发
人员可以定制关键类如ActionForm 和Action.
2.7 小结 今天的开发人员需要建立全特征的应用,并且可以随时维护。Web 应用框架,如 Struts,
些servlet 容器的兼容性测试。
truts 也构建于通用的设计模式,特别是 MVC 架构。框架鼓励应用采取分层设计。这种
决方案。它绝不会抑制你的应用,并有随处有一些免费资源
尽管有一些阻碍, Struts 也很容易地成为现今最流行的Web应用框架。
过头来运行Struts,并创建另一个应用。
解决了这个普遍问题,所以开发人员可以专注于它们应用的特定功能。在开发Web应用时,框架特别重要,因为HTTP 和 HTML 要创建动态应用非常困难。 Struts 使用了大多数标准的Java servlet API 并成为一S设计使应用具有强壮性和伸缩性。 架构的一个关键之处是它扩展了HTTP 请求-响应循环的流程。Struts 控制器管理着应用使用的路径,帮助安全的收集用户输入,并可以本地化应用消息,特别是错误消息。 Struts 是一个富有效率的解可以使用。 当然, Struts 还有一些缺陷。许多类名的选择在开发时显得比较轻率,容易引起混淆。其他一些地方也值得改进。

浙公网安备 33010602011771号