5
用
ActionForm
进行复制
与Ted Husted 和 George Franciscus合著
本章包含
理解ActionForm生命周期
检查ActionForm的职责
讨论ActionForm设计特征
使用ActionForm的最佳实践
组装和报告ActionForm
介绍Scaffold BaseForm
5- 5- 1 -
The sweat of hard work is not to be displayed. It is much
more graceful to appear favored by the gods.
—Maxine Hong Kingston,
The Woman Warrior: Memoirs of a Girlhood among Ghosts
5.1
吃的是草,挤出的是奶
使用Web应用的人通常会花费大量的时间通过HTML form提交数据。有时是一些新的
数据,通过填写空白表单来提交。而其它时候,则可能是将修改过的数据重新提交。
HTML form 给Web开发人员提出了两个挑战:一是在数据被提交时获取数据,以及使
用用户可以修改的数据预装一个表单。如果用户选择一个必须被修改的地址记录,我们就需
要将数据从记录拷贝到HTML form。这就意味着,我们必须能够通过传送动态值来针对每
次请求改变页面。
HTML 并没有提供一个内建的手段来使用动态值预组装一个控件。需要定制的页面由
混合了静态和动态的组件以一种特殊的方式写成,作为运行时的响应。
这里有许多方式为Java Web应用编写动态页面,最通常的办法是JavaServer页面。Struts
分发包包括了一套JSP标签,你可以用来编写动态 HTML 控件。像其它许多标签库一样,
Struts 标签设计来同JavaBeans一起工作。如我们在第一章所见,JavaBean 是一个遵循一
定设计规则的简单但是非常强大的对象。
不像 HTML 元素, Struts 标签提供了标准的方式来组装控件。每个 HTML 标签对
应一个标准的HTML标记元素。每个JSP 标签都有一个属性项提供bean中的属性名称。
JavaBean属性的返回值用于控件的value 属性。
所以,如果有一个元素象这样:
<input name="address"/>
它可以由这样的Struts
JSP 标签来代替:
<html:input property="address"/>
标签会从Javabean中检索
address 属性,并将它作为HTML 元素的 value来插入。当浏
览器获取这个标签,它可能看起来像这样:
<input name="address" value="6 Lost Feather Drive"/>
这里,他实际上是调用
ActionForm的getAddress()方法,返回字符串"6 Lost Feather
Drive"。
注
在某些编程上下文中,词语 “属性(property)”等同于 attribute, field,或者 variable。在这些场合, 属性
(property)表达了一个存储地址。JavaBean 属性(property)通常使用字段/域(field)来存储值, 但
是 JavaBean “properties”确实说来是可以用来检索值的方法。当我们说一个公共属性public properties,
我们实际上是在说 JavaBean 对象的公共域。我们说的方法则是用来检索和设置值的。有时候,这些值存
储于域(field)中。其它时候,它可能是从几个域中计算出来,或者从其它对象中检索出来。JavaBeans
5- 5- 2 -
的强大之处在于对象可以控制值的存储方式,以及使他们可以通过mutator 和accessor方法进行公共存取。
为完成这个流程,当表单被提交到Struts 控制器, 它将HTTP 参数传递给 JavaBean。
大部分来自于HTML 表单的输入都将在传递给业务层之前进行校验。如果一个字段假定是
包含数字,我们就得确保它就是数字。如果校验检查失败,我们可以将 JavaBean 回传给
页面。然后JSP 标签根据JavaBean 属性重新组装HTML元素,用户就可以纠正输入,并重
新尝试。
JavaBean 都可以和 Struts JSP 标签一起来组装控件。但要提供输入的自动校验,
Struts使用它自己的JavaBean 子类, 称作 ActionForm。
一旦从HTML表单的输入传递给ActionForm bean,并且属性经过了校验,属性就要作
为一个漂亮整齐的JavaBean传递给Action。Struts Action 对象使用form bean来进行其业务
操作,处理错误,并选择相应响应页面。第8章将详细讨论Action 对象。
5.1.1 ActionForm
的要求
创建一个ActionForm 并不困难,但是你的类必须符合一些要求:
ActionForm 必须扩展自org.apache.struts.ActionForm。基类 ActionForm 是不能实
例化的。
ActionForm 必须为每个应该从请求中收集的HTML控件定义一个公共属性。
(Struts 1.0
要求每个属性都要
mutator
和
accessor
。
Struts 1.1
则没有如此严格
)
ActionForm还可能要符合一些可选的要求:
如果你要求ActionForm 在传递属性到Action之前校验它们,你就必须实现validate
方法;
如果想在组装前初始化属性,必须实现 reset , 它在ActionForm 组装前被调用;
下面是一个简单的ActionForm 类:
import org.apache.struts.action.*;
public class MyForm extends ActionForm {
protected String name;
protected String address;
public String getName()
{return this.name;};
public String getAddress()
{return this.address;};
public void setName(String name)
{this.name = name;};
public void setAddress(String address)
{this.address = address;};
};
在Struts 1.1, 你也可以使用 DynaActionForm 类来在Struts 配置文件中宣称你的属性。下
面是一个简单的使用DynaActionForm的ActionForm:
<form-bean
name="myForm"
5- 5- 3 -
type="org.apache.struts.action.DynaActionForm">
<form-property
name="name"
type="java.lang.String"/>
<form-property
name="address"
type="java.lang.String"/>
</form-bean>
关于Struts 配置 文件的详细情况,请参见第4章。
虽然ActionForm的要求非常简单,但它在许多应用的开发中都扮演了令人惊奇的强大
角色。ActionForm也许是Struts 框架最令人费解的部分。这个“勤劳”的JavaBean扮演了
一个域收集器、防火墙、类型转换器、数据缓冲器以及传输对象。
有时它们似乎显得是多余的,有时它们的价值又是无法估量的,但是每次,它们都是框
架的焦点部分—也是Struts之所以是 Struts的关键部分。
5.2
千面女郎
ActionForm
ActionForm是一个多能的对象。就像我们先前解释的,它可以扮演字段收集器,防火
墙,数据缓冲, 数据校验器,类型转换器,以及传输对象——在一个单一请求的范围内的所
有东西。让我们一一来看看它可以在应用充当的角色。
5.2.1 ActionForm
作为字段收集器
绝大部分应用都需要用户数据。许多应用甚至需要大量的数据。在web 环境中, 有效
收集数据成了其一大挑战之一。
HTML 定义了一个几乎不能使用的数据输入控件。HTTP 也定义了一个几乎不能使用
的数据传输协议。Struts 使用 ActionForm来帮助补偿HTML和HTTP的不足。HTTP 是个
如此的简单协议,它使用可能是最基本的方式来传输数据。但作为协议本身,它非常易于实
现,并且在它自己的方式上似乎运行的非常有效率。但作为应用使用, HTTP将许多实现细
节作为考验留给了开发人员。
5.2.1.1
通过
HTTP
提交字段
当一个HTML 表单通过HTTP被提交, 所有的内容都被视为文本。web 服务器接收到
的表单元素是以名-值对的方式来到的。它们是文本字符串,不是二进制数据。
下图是一个简单的表单,两个字段,Name 和Amount。
5- 5- 4 -
图表 5-1 有两个字段的简单表单
而下图则是浏览器要提交这个表单的URI.
图表 5-2 来自表单的 Get 请求
而如下图,POST 方法则可以用来隐藏提交的内容,但结果是一样的:表单中输入的内
容被作为名-值对编码进URI之中。
图表 5-3 来自表单的 POST 请求
定义
HTTP 规范允许表单数据作为URI的一部分进行提交,但不是每个字符都可以用在URI之中。如果其它字符
需要被表单数据使用,他们必须先进行编码。 URL 使用% 符号,紧跟两位十六进制ISO-Latin代码数据
(非大小写敏感)。详细内容见 RFC 1738 和 2396 [W3C URL; W3C URI]以及 HTML 4.01规范 17.13.4
[W3C HTML4].
5.2.1.2
通过
HTTP
提交文件
一些表单允许将文件作为一个附件进行上载。这时,附件要进行特殊编码,以便仅使用
文本内容被提交。这样就允许我们通过HTTP传递二进制文件, 文件被转换成文本字符流来
传输,然后又被转换回来。
5.2.1.3
通过
HTTP
提交空字段
如果一个文本字段是空白的, 大部分浏览器都会提交一个空参数。但是如果一个选择框
是空白的,浏览器则根本不提交任何东西。应用必须根据浏览器没有提交选择框时判断出,
意味着它一定是false 或者 null。实践中,这仅适用于选择框,但规范允许浏览器忽略任何
5- 5- 5 -
评论0