370 附录C Struts标签参考
附录C Struts标签参考 371
Struts标签参考
这
个附录是关于所有Struts 标签的参考,这些标签来自于5个标签库:HTML、Bean、Logic、Nested和Tiles标签库。其中也包括了有关Struts-EL和JSTL(参见第10章)的用法示例和相关信息,以及JSF和Struts-Faces集成标签库(见第20章)里面所适用的对等标签。这个参考不包括废弃的Template标签库,它已经被Tiles标签库所取代。
为了使这个参考更加紧凑,我们在一个或者多个公共属性集下面收集了那些出现在多个标签中的属性。这些公共属性集是在描述每一个标签库的各个小节的开始时介绍的。
HTML标签库
HTML标签库中的定制标签本质上与普通的HTML <form>标签和它相关联的输入标签,比如各种各样的<input>标签,之间具有一一对应关系。
这个标签库的目的是为了能够将视图层连接到Struts Web应用程序的控制器层。这两者之间的连接主要是在文件中完成的。
HTML库中的标签根据功能可以分为4个组:
· 表单标签。这些标签将数据从视图传递到控制器。这些标签几乎与它们的HTML对应物(<form>标签以及各种各样的HTML数据输入标签)是一一对应的关系,但是也有额外的,Struts特有的、能够更好地使视图和控制器之间的数据传递更加容易的标签(例如,multibox标签)。
· 消息标签。这些标签(在视图层)显示源于控制器的消息。
· URL标签。这些标签是需要URL才能工作的普通HTML标签的对应物。Struts版本的这种标签的存在主要是为了允许使用全局转发的名称而不是实际的URL。
· 杂项标签。这些标签没有明确的功能分组,所以必须单独处理。
表C-1到表C-4根据其功能分组列出了这些标签的概要说明。
表C-1到表C-4中的信息基于那些标签的Apache文档。
Apache许可证的一份副本可以在
表C-1 HTML标签库的表单标签
标 签
用 法
form
定义一个表单
checkbox
产生一个复选框输入字段
file
产生一个文件选择输入字段
hidden
产生一个隐藏字段
multibox
产生多个复选框输入字段
radio
产生一个单选按钮输入字段
select和option、options或 optionsCollection
select产生一个下拉列表。option元素嵌套在select中,并且为外围的select元素产生选项
text/password
产生一个文本/口令输入字段
textarea
产生一个HTML文本区域输入字段
image
产生一个input字段图像
button
产生一个按钮输入字段
cancel
产生一个取消按钮
submit
产生一个提交按钮
reset
产生一个复位按钮
表C-2 HTML标签库的消息标签
标 签
用 法
errors
显示错误消息
messages
在错误消息和消息集之上进行迭代(参看<logic:iterate>条目对这些术语的描述)
表C-3 HTML标签库的URL标签
标 签
用 法
base
产生一个HTML <base>标签。这样将创建一个参考,从此开始,JSP中的所有相对路径都根据此来计算
img
产生一个HTML <img>标签
link
产生一个HTML超链接
rewrite
扩展一个给定的URI。这在为创建输入到Java脚本函数中的URL的时候很有用的
表C-4 HTML标签库的杂项标签
标 签
用 法
html
产生一个<html>标签。也包括来自用户会话的language属性
xhtml
告诉页面中的其他标签将自己呈现为符合XHTML 的标签
frame
产生一个HTML框架(frame)
javascript
指示自动产生的JavaScript的位置。用于与Validator框架一起使用时,如第15章所述
公共属性集
有些属性对于多个HTML库中的标签都是通用的。这些标签可以很自然地分组成几个公共属性集,随后将描述。我们将给每个属性集一个缩写,这个缩写将用在后面对每个标签的描述中。
1. 事件处理器属性集
这个最大的属性集由那些相当于HTML事件处理器属性的属性组成。Struts版本的属性完全和HTML版本的属性相同。我们将其称为事件处理器属性,或者简称evt-attrs。在这个属性集中的属性列于表C-5中。这个属性集中的每个属性的值都是一个在特定的动作发生时需要调用的JavaScript函数(例如,鼠标单击、失去焦点等)。如果熟悉HTML,表C-5应该没什么问题。
表C-5 事件处理器属性集
属性名称
触发器
onblur
元素失去焦点
onchange
元素的值发生改变并且元素失去焦点
onclick
元素被单击
ondblclick
元素被双击
onfocus
元素获得焦点
onkeydown
当元素具有焦点时,键被按下
onkeypress
当元素具有焦点时,键被按下然后释放
onkeyup
当元素具有焦点时,键被释放
onmousedown
当指针在元素之上时,鼠标按钮被按下
onmousemove
鼠标指针被移动到元素之上
onmouseout
鼠标指针离开元素
onmouseover
鼠标指针进入元素
onmouseup
当指针在元素之上时,鼠标按钮被释放
2. 可访问性属性集
下一个属性集也与HTML有关,并且这些属性有助于提高可访问性。
表C-6列出了这些标签,我们将其称为可访问性属性集,或者简称acc-attrs。
表C-6 可访问性属性集
属性名称
用 法
accesskey
指定如果某个键被按下,将导致该元素获得焦点
alt
指定此元素的备用文本
altKey
指定备用正文的消息资源关键字
tabindex
指定此元素的 Tab键次序的一个正整数
title
指定此元素的建议的标题。在大多数图形浏览器中,建议标题将在鼠标指针越过元素的时候表现为一个工具提示
titleKey
指定建议标题的消息资源关键字
表C-6中的大多数属性只不过是它们的HTML对应物的镜像。其中的例外是altkey和titleKey,它们使用Struts的消息资源文件来生产实际属性(分别是alt和title)的一个本地化版本。
3. 呈现属性集
呈现属性集(ren-attrs)由那些指定对应于一个标签的底层HTML元素的最终呈现的属性组成。这些属性被列出在表C-7中。
表C-7 呈现属性集
属性名称
用 法
disabled
这个boolean属性禁止(disabled = " true ")输入元素。在大多数图形浏览器中,这将导致HTML元素变成灰色
style
指定该元素的CSS样式
styleClass
指定此元素的CSS样式表。styleClass相当于HTML class属性
styleId
指定被分配给此元素的HTML ID。也就是说,styleId相当于HTML id属性
4. Struts属性集
Struts属性集(struts-attrs)由那些通常专门用于Struts的属性组成。这些属性被列出在表C-8中。
表C-8 Struts属性集
属性名称
用 法
bundle
指定要使用的消息资源束。如果这个属性没有被指定,将使用默认的文件。资源束是在Web应用中使用多个消息资源文件的方式。注意,当前对这个特征的支持是不充分的,使用它会导致维护复杂化。bundle属性将在<bean:message>条目中更详细地解释。这个属性是Struts 之后新引入的
indexed
这个boolean属性只有在外围的标签被嵌套在<logic:iterate>标签的内部才是有效的。如果设置为true,呈现后的HTML标签的名称将被索引,例如,myProperty [12]。括号中的数字将根据包围的<logic:iterate>标签的每一个迭代增加
property
在表单被提交时将使用的请求参数或HTML POST元素的名称设置为指定的值(见下一个条目)
value
输入元素的值。这个值将被提交给控制器层,可以在请求参数中或者在HTML POST本身中
5. 错误样式属性集(+)
错误样式属性集(err-attrs)是从Struts 以后新引入的。这些属性将使你能够在一个给定的输入元素发生验证错误的时候指定一个错误样式。表C-9描述了这些属性。
表C-9 错误样式属性集
属性名称
用 法
errorKey
将在其下保存错误消息的关键字。只有在同时也指定了关联的<html:errors>的name属性的时候才需要指定这个属性。这两者必须相同
errorStyle
有错误发生时该元素的CSS样式
errorStyleClass
有错误发生时该元素的CSS样式类的名称
errorStyleId
分配这个新的标识符到该元素,如果有一个错误消息针对它的话
HTML标签库的Struts-EL标签
HTML库中的全部标签都有“EL使能”的版本。
注意
EL使能的标签是指那些允许使用EL表达式的标签。参看第10章的例子。
base
这个标签允许方便地创建一个HTML <base>标签。
HTML <base>标签允许指定一个基础URL,并以此为准来推算JSP中的相对路径(例如,../../或者)。这个URL是使用外围JSP页面的绝对路径来解析的,但是这并不是必要的情况。能够保证这样的唯一方式是使用<base> 标签,或者更方便地,使用<html:base>标签。
1. 使用限制
<base>和<html:base>都必须是HTML的<head>标签的子标签。
2. 属性
· server
:指定基础URL。如果省略了server属性,Struts将复制外围JSP页面的路径。server属性将被呈现为<base>的href属性。
· target:如果应用中使用了框架,那么可以在定义该框架的页面中指定这个基础URL所适用的框架名称。
3. 示例
最简单的、并且最有用的例子是独自使用<html:base >标签:
这意味着base就是JSP页面本身。这将被呈现为:
同样地,如果想要固定当前Web应用程序中的框架的base,可以这样使用:
如果需要设置base来指向另一个服务器,可以使用server属性:
4. 对应物
Struts-Faces 标签库(见第20章)包含了<s:base>标签,它可接受target属性。但是, server属性则没有对应物。
使用<html:base/>标签的一个技巧是:
button
<html:button>表示一个HTML按钮。单独使用它,<html:button>什么都不会做。例如,它不会提交表单。必须使用一个(或者多个)事件处理属性(见evt-attrs)来激活一些JavaScript以便执行一些感兴趣的事情。
注意
尽管当前的Apache Struts联机文档说,按钮的值不会被作为一个URL参数发送。
如果想要显示一个由一个图形定义的按钮,那么应该使用<html:image>代替。
1. 使用限制
这个标签必须用在一个<html:form>标签之内。必须指定property属性。
2. 属性
前4个公共属性集(evt-attrs、acc-attrs、ren-attrs和struts-attrs)都是可以接受的。唯一必需的属性是property。如果其值没有被指定,并且如果没有在<html:button>的标签体中呈现文本,那么按钮文字将默认为“Click”。
3. 示例
这段代码将呈现为一个具有“Click”文本标注的HTML按钮,当其被单击时,将调用JavaScript函数changeMode():
在这段代码中,假想的JavaScript函数可能会测试 = = "button1"来决定哪个按钮被单击了。
下一个例子展示了3个按钮,它们都有文本“Click Me”。最后一个按钮使用一个<html:bean>来本地化它的文本:
4. 对应物
JSF的<h:commandButton>标签要更加强大些,并且允许使用action属性将一个按钮轻易地连接到服务器端的某个函数:
当然,如果要在Struts中使用这个标签,需要将它嵌入到Strut-Faces <s:form>标签内部。参看第20章关于<h:commandButton>和<s:form>的更多细节。
cancel
这个标签在一个表单上显示一个取消按钮。单击这个按钮将导致外围的表单被提交,但是简单验证会被绕过。然而,表单相关的Action的execute()函数则会被正常调用,以显示下一个页面。当然,这意味着Action子类必须具有专门的逻辑来决定取消按钮是否被单击了(参见本小节中的“示例”一小节)。
当表单数据被提交时,Cancel 按钮中的文本也会被作为请求URL中的一个参数被发送。
1. 使用限制
这个标签必须用在一个<html:form>标签之内。不能随意指定property属性,这样做将导致取消按钮不被Struts接受。
2. 属性
前4个公共属性集(evt-attrs、acc-attrs、ren-attrs和struts-attrs)都是可以接受的。然而,不要随便指定property属性。如果其值没有被指定,并且如果没有在<html:cancel>的标签体中呈现文本,那么按钮文字默认为“Cancel”。
3. 示例
下列3个例子展示了3个取消按钮,它们都有文本“Cancel Me”。最后一个取消按钮使用了一个<html:bean>来本地化它的文本:
为了能够检测到取消按钮是否被单击了,可以在Action的execute()中使用这段代码:
4. 对应物
JSF 的<h:commandButton id = " cancel " type = " SUBMIT " >允许仿真<html:cancel>按钮的功能。当然,为了和Struts一起使用这个标签,需要将它嵌入到Strut-Faces <s:form>标签中。更多关于<h:commandButton>和<s:form>的细节参见第20章。
checkbox
这个标签将呈现为表单内的一个复选框输入字段。参见<html:multibox>。
1. 使用限制
这个标签必须用在<html:form>标签之内。property属性是必需的。ActionForm上的对应属性必须是一个布尔类型的属性。
2. 属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。有4件重要的事情需要注意:
· ActionForm子类上的对应属性必须是一个布尔类型的属性。
· value属性指定如果复选框被选择将要传递给setXXX()的参数。所以,如果指定value = " true "(或yes),那么setXXX(true)将在复选框被选中的时候就会被调用。假定对value属性使用任何其他的设置,如果复选框被选中,则setXXX(false)会被调用。
· 复选框被呈现为选中状态只有在其值等于getXXX()返回值的时候才会发生。所以,如果value = " true "(或on或yes)并且getXXX()也返回true,那么复选框会被呈现为选中。同样地,如果value不是true(或on或yes)并且getXXX()返回false,那么复选框也会被呈现为选中。
· ActionForm子类上对应的setXXX()函数只有在复选框被选中的时候才会被调用。这意味着为了使应用能够探测到一个未选中的复选框,需要在ActionForm的reset()函数中调用setXXX()。reset()函数会在一个表单被显示(或者重新显示)之前被Struts自动调用,并且是在任何setXXX()函数被调用之前。
3. 示例
代码
将被呈现为两个复选框字段。对应的ActionForm可能是:
pregnant属性是很简单明了的:如果用户选择了相应的复选框,那么会被直接地翻译为pregnant属性。nonsmoker属性则不那么明显:被保存的基本属性实际上与nonsmoker是相反的。这仅仅是一个方便做法,但是,可以看出,它造成了混乱的代价。
一个备选的、较少混淆的方式是,JSP 表单和ActionForm子类的代码都这样编码:
注意,我们删除了value = "false"。ActionForm子类现在是:
4. 对应物
JSF的<h:selectBooleanCheckbox>是一个对应物。可以将其包围在Struts-Faces <s:form>元素中,以便Struts能够处理提交的值。
errors
这个标签显示一个或多个错误消息。如果没有发现匹配的错误消息,则什么都不会被显示。参见<html:messages>,它可在错误和普通消息之上进行循环。
1. 使用限制
无。
2. 属性
· property:用它来检索错误消息的关键字。注意,可能有不只一个错误信息保存在同一个属性之下。如果指定property,那么会显示全部的错误消息。这个技巧在调试的时候是非常有用的。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。Locale属性指定一个可以用来在当前会话中查找Locale对象的关键字。bundle属性将在<bean:message>条目中详细解释。可以使用这些属性来指定一个不同于当前用户场所的场所,或者一个不同于默认资源文件的消息资源文件。
· name:持有错误消息的对象的名称。如果希望使用Struts的默认错误报告机制,请不要指定这个属性
。
· prefix/suffix:它们都是被呈现在每个错误信息之前和之后的文本的关键字。例如可以在消息资源文件中设置
:
那么就可以这样使用这些属性:
错误信息将被显示为
· header/footer:这些属性类似于prefix/suffix,但是它们适用于一列错误消息的开始和结束。这在有不只一个消息要被显示的时候才会发生。
3. 示例
通常,可以放置一个<html:errors>到一个输入元素附近,来显示该输入元素的相关错误消息。如下所示:
4. 对应物
Struts-Faces集成库中的<s:errors>标签是一个对应物。
file
这个标签可以允许容易地进行文件上传。
注意
第11章包含了对此标签的更完整的说明。
1. 使用限制
property属性是必需的。它必须是<html:form>标签的一个子标签。
2. 属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。
除此之外,还有几个专门针对file的属性:
· accept:可接受的文件扩展名的一个用逗号分隔的列表。这些是被浏览器显示的。不幸的是,大多数浏览器都会忽略这个信息。
· size:显示字段的长度。如果省略,决定权便留给浏览器。
· maxlength:可接受的最大字符数。默认允许无限的字符数。大多数浏览器忽略这个属性。
3. 示例
请参阅第11章。
4. 对应物
没有纯JSF的对应物。但是MyFaces支持一个名为<x:inputFileUpload>的扩充,它巧妙地进行了一些改进。用于访问上载文件的机制非常类似于Struts的FormFile(它调用UploadedFile)。然而,这带来了一些麻烦,因为当前的Struts-Faces集成库()不能用于MyFaces。
form
表示一个HTML表单。它也是许多输入标签的强制的父元素。
1. 使用限制
Action属性是必需的。
2. 属性
除了ren-attrs属性之外,form还接受下列属性:
· action:处理这个表单内的数据的表单处理器的名称。这个属性是必需的。
· method:这个form的HTTP提交方式,POST或GET,默认是POST。
· focus/focusIndex:focus指定在表单被第一次加载的时候,取得焦点的表单中的那一个字段的名称。Struts会自动产生JavaScript来处理这个事情。如果focus属性没有被指定,那么不会产生这样的JavaScript。focusIndex应用于被索引的输入元素。可以指定获得焦点的元素的索引。
· enctype:指定当提交这个表单的数据的时候所使用的编码。只有在表单中有一个<html:file>输入元素的时候才需要设置这个属性(详细信息参见对应的条目,或者参看第11章)。
· onsubmit/onreset:这些属性引用的是当这个表单被提交或者复位的时候,被调用的JavaScript 事件处理器的名称。
· acceptcharset:对此表单有效的字符编码(从Struts 开始)。这是一个标准的HTML属性。
· readonly:如果被设置为true,意味着表单数据不能被编辑。
· scriptlanguage:如果被设置为false,将忽略产生的<script>标签中的language属性。如果指定了XHTML呈现,这个属性也将被忽略。
· target:这个表单的数据被提交到的窗口的名称。这个是一个标准的HTML属性。
3. 示例
通常,可以指定action和focus属性:
4. 对应物
Struts-Faces <s:form>是<html:form>最好的替代。细节参见第20章。
frame
呈现为一个HTML <frame>。使用<html:frame>的好处在于可以使用全局转发或表单处理器来轻易地将内容放入frame中。
1. 使用限制
必须指定action/ module、href、page或者forward属性。
2. 属性
· action/module、href、page或forward:用于为frame指定一个URL。action/module属性对指定一个表单处理器。当然,action必须以一个“/”开始,并且如果想要指定一个模块,可以使用module属性。href可以是一个相对的或者绝对的URL。page是一个相对于module的URL(因此必须以一个“/”开始)。forward是一个全局转发的名称。
· anchor:一个作为链接的可选的HTML锚。
· paramname、paramproperty、paramscope和paramid:使用这些属性来创建一个请求参数。请求参数是附加到最后的URL之上的。第一个属性用于在当前请求或会话中定位一个对象。这个对象的toString()就是一个参数值。参数名称由paramId给出。参看<html:link>中的一个例子。
· name/property/scope:使用这些属性来创建多个参数。请求参数是附加到最后的URL中的。这些属性用于定位一个类型为的对象。Map的关键字是参数名,并且对应的值就是参数值。如果指定property属性,必须也指定name属性。参见<html:link>中的一个例子。
· transaction:如果为true,则附加当前的事务令牌到URL中作为一个请求参数。参看<logic:present>条目获得关于事务令牌的详细信息。
· title/titleKey:这些属性的细节参见acc-attrs属性集。
· style/styleClass/styleId:这些属性的细节参见ren-attrs属性集。
· scrolling:指定如果必要时是否自动创建卷动条(scrolling = " auto "),或总是(yes)或从不(no)。
· marginheight/marginwidth:指定顶端和底部边距的高度(marginheight)或左边和右边边距(marginwidth)。单位是像素。
· frameborder:指定需要呈现一个边线(frameborder="1")或不需要(frameborder="0")。
· framename:呈现为的<frame>的名称。
· noresize:一个逻辑属性,指示这些frame是否可以缩放(false)或是否它的大小是固定的(true)。
· longdesc:frame的更长的描述URL。这个属性是一个标准的HTML属性,详细细节可参考HTML参考。
· bundle:允许选择一个不同于默认值的资源文件。bundle属性在<bean:message>条目中还会详细解释。
3. 示例
下面是一个具有两个frame的页面:
4. 对应物
无。
hidden
这个标签表示一个隐藏表单字段。
1. 使用限制
property属性是必需的。它必须是<html:form>标签的一个子标签。
2. 属性
前5个公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs和initattr)都是可接受的,并且都有其通常的意义。
除此之外,还有个write属性,如果被设置为true,将导致这个隐藏字段的值会被显示。这在调试时是有用的。
3. 示例
代码
指定一个隐藏字段,持有当前的表单bean上的名为clientId的属性的值。还可以这样指定一个value属性:
读取表单数据的Action子类就可以根据隐藏字段的值来进行分派。请看<bean:define>条目获取另一个有用的例子。
4. 对应物
JSF的<h:inputHidden>是<html:hidden>的一个对应物,但是需要将它包围在Struts Faces <s:form>标签之内,以便关联的表单bean能够被提交的值填充。
html
这个标签插入<html>…</html>标签,并且language属性等于当前的用户的场所。
1. 使用限制
无——如果使用它,其他的Struts标签应该被嵌套在它内部。
2. 属性
· xhtml:如果被设置为true,将导致被嵌套的Struts标签按照XHTML 规范呈现它们自己(参见<html:xhtml>)。
· lang:(自从之后)。如果设置为true,将在最后的<html>标签中加入一个lang属性。属性值按以下顺序搜索:(1)当前会话的场所;(2)accept-language HTTP请求header;(3)该服务器的默认场所。参考HTML参考文档来理解如何使用HTML的lang属性。
3. 示例
下面说明了如何呈现一个符合XHTML 规范的页面:
4. 对应物
Struts-Faces集成库中的<s:html>标签是一个对应物。
image
这个标签被呈现为一个HTML image 输入字段。单击这个图像将导致外围的表单被提交。
1. 使用限制
这个标签必须用在<html:form>标签之内。需要指定src、srcKey、page或pageKey属性。
2. 属性
前4个公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs)都是可接受的,并且都有其通常的意义。除property属性(稍候解释)外。有几个专门针对image的属性:
· property:这个属性指定返回一个JavaBean的基础对象上的函数,该对象具有setX(int x)和setY(int y)函数,以保存鼠标单击这个图像输入字段时的x、y坐标。如果想要使用基础对象上的setx()和setY()函数,可简单地使用property = " "。
· src/srcKey/page/pageKey:使用这些属性之一来指定将要使用的图像。src是图像的URL。page是图像相对于module的URL(并且因此必须以“/”开头)。key是指向实际的URL的消息资源关键字。
· 显示图像周围边线的宽度。单位是像素。
· locale:指定一个可用于查找保存在当前会话中的Local对象的关键字。这个对象被用来决定所用的任何关键字的值。如果省略,将使用默认的Struts消息资源文件。
3. 示例
下面的代码在JSP中显示了一个图像输入字段:
对应的ActionForm子类可能是:
4. 对应物
无。
img
这个标签被呈现为一个HTML <img>。
1. 使用限制
必须指定这些属性之一:action module或src/srcKey或page/pageKey。
2. 属性
前3个公共属性集都是可接受的:evt-attrs、acc-attrs和ren-attrs。除了这些之外,还有几个专门针对img的属性:
· action/module或src/srcKey或page/pageKey:用于定位需要显示的图像。第一个action/module属性对指定一个表单处理器。当然,action必须以一个斜杠“/”开始,并且如果想要使用一个模块,则需指定module属性。src是该图像的URL。page属性是该图像相对于模块的URL(因此,必须从一个斜杠开始)。带了key的属性版本是指向实际的URL的消息资源关键字。它们对显示本地化图像是非常有用处的。
· border:指定显示在图像周围的边线的宽度。单位是像素。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。locale指定一个可用于查找保存于当前会话中的Locale对象的关键字。bundle属性将在<bean:message>条目中详细解释。
· align:指定图像相对于围绕的文本的对齐方式。这是<img>元素的一个标准HTML属性。有效值是left、right、top、texttop、bottom、absbottom、middle和absmiddle。关于这些值具体是什么意思请参考HTML文档。
· height/width:以像素为单位指定最后显示的图像的高度和宽度。图像的缩放是由浏览器进行的。
· hspace/vspace:指定在图像和围绕元素之间的横向间隔(hspace)和垂面间隔(vspace)的大小。单位是像素。
· imageName:呈现为<img>标签内的一个name属性,name = <imageName>。通常被用于脚本。
· ismap:这个逻辑属性是HTML <img>标签的ismap属性的对应物。它被用于指示一个服务器端的图像映射——它仅用于那些不懂得HTML <map>元素的较老的浏览器。为此,几乎不可能使用ismap属性。
· usemap:要使用的HTML <map>元素的名称。这将该图像转变成一个可单击的图像映射。关于如何创建一个<map>参见HTML参考。当用户单击该图像时,浏览器的行为完全是在客户端处理的,并不涉及到服务器端处理。如果想要将鼠标单击位置传递给服务器端代码,可使用<html:image>来代替。
· paramname、paramproperty、paramscope和paramid:可以使用这些属性来创建一个请求参数。请求参数是附加到最后的URL之上的。3个属性中的第一个属性用于在当前请求或会话中定位一个对象。这个对象的toString()的返回值就是一个参数值。参数名称由paramId给出。参看<html:link>中的一个例子。
· name/property/scope:使用这些属性来创建多个参数。请求参数是附加到最后的URL中的。这些属性用于定位一个类型为的对象。Map的关键字是参数名,并且对应的值就是参数值。如果指定property属性,必须也指定name属性。参见<html:link>中的一个例子。
· useLocalEncoding:如果设置为true,则告诉Struts针对当前HttpServletResponse使用什么字符编码。
3. 示例
下面是如何呈现一个本地化图像:
要懂得如何根据图像的URL创建一个或多个请求参数,参看<html:link>条目。
4. 对应物
JSF的<h:graphicImage>是一个对应物。
javascript
这个标签导致用于客户端验证的JavaScript的生成。这个标签与Validator框架联系非常紧密。
1. 使用限制
只有当它伴随一个<html:form>的时候,使用这个标签才是有意义的,因为产生的JavaScript用于客户端表单验证。JavaScript代码是由Validator框架自动产生的。所以,为了这个标签能够工作,ActionForm子类必须是ValidatorForm的子类。
2. 属性
这个标签最常见的应用是不定义任何属性。然而,可以通过使用下列属性对产生的JavaScript进行一些定制:
· bundle:指定用来产生错误消息的一个消息资源束(参见表C-8)。这个属性是在Struts 后加入的。参见<bean:message>条目。
· htmlComment:如果设置为true,则用HTML注解定界符(<!--和- - >)来包围该JavaScript。这是需要防止非常老的浏览器将JavaScript呈现到页面上所需的。如果使用了<html:xhtml>或者<html:html xhtml = "true">,这个设置将被忽略。默认值是true。
· cdata:如果cdata = "true",并且如果使用了<html:xhtml>或<html:html xhtml = "true">,产生的JavaScript是被XML的CDATA [...]定界符包围的。
· method:为自动产生的JavaScript的名称指定一个不同的前缀。使用这个属性来防止在自己的JavaScript和Struts产生的JavaScript代码之间的命名冲突。
· scriptlanguage:如果设置为false,忽略产生的<script>标签中的language属性。
· staticjavascript/dynamicjavascript:这两个属性都是逻辑值。staticJavascript(默认值是true)指定来源于Validator框架的静态JavaScript代码是否需要被粘贴到页面中。同样地,dynamicJavascript(默认值是true)指定为表单产生的动态的JavaScript代码是否需要被粘贴到页面中。通常情况下可能会省略这两个属性。
· src:这会将一个HTML src属性放入到被呈现的<script>标签中。可以使用这个属性来指定当页面被浏览器显示的时候想要加载的自己的JavaScript文件。
· page/formName:Validator框架允许创建多页验证(这个主题不是本书的内容)。这个特征在创建简化输入复杂数据的多页向导的时候是很有用的。典型情况是,一次展现给用户一个子表单,其中每个都有“next”和“back”按钮。page属性是当前页面的编号,而formName属性则是表单bean的名称。
3. 示例
最通常的用法是要求进行全部的验证。可以通过不指定属性<html:javascript/>来达到此目的。即使粘贴在页面的任何地方,这也是可以工作的。
4. 对应物
Struts-Faces集成库中的<s:javascript>标签是一个对应物。
link
这个标签呈现为一个HTML link。
1. 使用限制
必须指定action/module、href、page、forward或者linkName属性。
2. 属性
前3个公共属性集都是可接受的:evt-attrs、acc-attrs和ren-attrs。除此之外,还有几个专门针对link的属性:
· action/module、href、page或forward:用于为链接指定一个URL。action/module属性对指定一个表单处理器。当然,action必须以一个“/”开始,并且如果想要指定一个模块,可以使用module属性。href是针对该链接的URL。page是一个相对于模块的URL(因此必须以一个“/”开始)。forward是一个全局转发的名称。linkName是同一个页面中的另一个链接的名称。那个链接的URL也被用于这个链接。
· anchor:该链接的一个可选的HTML锚。
· bundle:用于指定一个不同的消息资源文件。bundle属性在<bean:message>条目中还会详细解释。
· transaction:如果被设置为true,附加当前的事务令牌到链接的URL中作为一个请求参数。参看<logic:present>条目获得关于事务令牌的详细信息。
· paramname、paramproperty、paramscope和paramid:使用这些属性来创建一个请求参数。请求参数是附加到该链接的最后的URL之上的。3个属性中的第一个属性用于在当前请求或会话中定位一个对象。这个对象的toString()的返回值就是一个参数值。参数名称由paramId给出。
· name/property/scope:使用这些属性来创建多个参数。请求参数附加到该链接的最后的URL中。这些属性用于定位一个类型为的对象。Map的关键字是参数名,并且对应的值就是参数值。如果指定property属性,必须也指定name属性。
· useLocalEncoding:如果设置为true,则告诉Struts针对当前HttpServletResponse使用什么字符编码。
3. 示例
这里是使用一个全局转发的简单的例子:
呈现后的链接会具有该success全局转发的真实位置。还可以为该链接包含请求参数:
本代码片段将呈现为一个具有一个名为action的请求参数的链接,该参数的值是由在bean myRequestValue中调用的toString()的返回值给出的。
下面是创建多重请求参数的代码:
4. 对应物
Struts Faces集成库的<s:commandLink>标签是一个对应物。也可以使用JSF的<h:commandLink>,但是会失去使用全局转发和表单处理器的能力。
messages
messages是错误消息和消息的一个迭代器——请参阅<logic:messagesPresent>条目获得对这两个术语的详细解释。默认的<html:messages>是一个错误消息之上的迭代器,但是可以通过设置messages属性为true来在消息之上迭代。单独使用它,<html:messages>不输出错误消息或者消息。必须嵌套一个适当的标签到它内部(例如<bean:write>)来显示具体内容。
1. 使用限制
id属性是必需的。
2. 属性
· id:这个属性的表现几乎与<logic:iterate>的id属性一样——它暴露一个引用单个消息的变量。
· message:一个逻辑属性,指示是否在错误消息(false或忽略)或消息(true)之上进行迭代。
· property:用它来检索消息的关键字。注意,可能有超过一个错误消息保存在同一个属性之下。如果property没有被指定,那么全部的消息都会被显示。这个技巧在调试的时候是非常有用的。
· name:持有消息的对象的名称。如果希望使用Action的saveErrors()或saveMessages(),不要指定这个属性。
· header/footer:这两个都是将在整个迭代开始和结束时呈现的文本消息资源关键字。只有当超过一个错误信息需要被显示的时候这才会发生。细节参见<html:errors>条目。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。Locale属性指定一个可以用来在当前会话中查找Locale对象的关键字。bundle属性将会在条目<bean:message>中详细解释。可以使用这些属性来指定一个不同于当前用户场所的场所,或者一个不同于默认资源文件的消息资源文件。
3. 示例
这就是显示全部错误消息的一个简单例子:
记住,错误消息在简单的验证失败(参见第6章)或者使用Action的saveErrors()(参见第7章)进行注册的时候都会出现。下面是如何显示消息:
消息的创建完全与错误消息的创建相同,但是它们是通过Action的saveMessages()方法来注册的,该方法和saveErrors()具有完全相同的方法签名。
下面是如何显示一个页眉和页脚(如果有一些错误消息要显示的话):
这里假定消息资源关键字和已经在文件中定义了:
所以HTML bold标签(<b>)将会在迭代的开始和结束输出。
4. 对应物
这个标签没有对应物,但是可以容易地创建一个技巧:错误消息是被存储在关键字_KEY之下的,而消息被保存在_KEY之下。两者都是被保存在请求中的。Globals是一个Struts类(),包含了各种各样的常数。所存储的对象可以是一个ActionMessages或者ActionErrors实例。可以使用JSTL的<c:set>标签轻易地创建一个对这些对象的引用,并且在页面中使用经过定义的消息对象。
multibox
这个标签将根据潜在数组呈现一个或多个复选框输入字段。参见<html:checkbox>。
注意
然而不同于<html:checkbox>,其关联的ActionForm上对应的属性不必是一个逻辑值。任何类型的数组均可。
1. 使用限制
这个标签必须用在一个<html:form>标签之内。必须指定property属性。
2. 属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。
有几个重点需要注意:
· 返回值可以通过value属性或者嵌套在该标签体内部的内容来指定。
· 为了使用这个标签,通常会将它嵌套到一个<logic:iterate>(或任何其他的兼容循环构造,比如JSTL的<c:forEach>)之中,并且使用scriptlet或这个标签的EL使能的版本来动态地设置value属性(如果需要嵌套内容,那么就必须使用scriptlet)。
· 只有当复选框被选中的时候值才会被提交。这意味着为了探测一个被清除的复选框,需要设置基础的数组为一个零长度的数组。对此参见下面的例子。
3. 示例
考虑一个表单中的<html:multibox>:
和关联ActionForm的子类:
_ids变量的长度是不固定的——这取决于被呈现的检查框有多少被选中了。
4. 对应物
无。
radio
这个标签被呈现为一个单选按钮输入字段。
1. 使用限制
这个标签必须用在一个<html:form>标签之内。必须指定property属性和value属性。
2. 属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。
除此之外,还有一个idName属性,它指向一个JavaBean。当idName被指定时,value属性被用作这个JavaBean的一个属性名。它们结合起来用于指定该单选按钮的一个返回值。
3. 示例
下面是一个表单上有几个单选按钮的例子。注意所有的单选按钮都是如何引用同一个属性(color)的,从而允许用户从一个列表中选择一个颜色:
下面是使用idName属性的同一个例子:
在第二个例子中,colors是一个可迭代的对象(参见<logic:iterate>条目)并且持有JavaBean(在此段代码中被暴露为变量c),它具有一个getColor()函数。
4. 对应物
JSF的<h:selectOneRadio>是一个对应物。
reset
这个标签显示一个如果被单击后,将导致外围的表单中的字段被清除的按钮。
1. 使用限制
这个标签应该用于一个<html:form>标签内部。
2. 属性
前4个通用属性集(evt-attrs、acc-attrs、ren-attrs和struts-attrs)都是可以接受的。如果其值没有被指定,并且如果没有在<html:reset>标签的标签体中呈现文本,那么按钮文字默认为“Reset”。
3. 示例
这个例子展示了3个提交按钮,所有的按钮的文本都是“Reset Me”。最后一个Reset按钮我们使用了一个<html:bean>标签来本地化它的文本:
在所有情况下,如果用户单击该按钮,表单会被提交,关联的ActionForm的reset()函数会被调用,并且页面会被重新显示。ActionForm子类可以覆写这个函数,以提供对表单字段的定制重设行为。
4. 对应物
JSF的<h:commandButton id = " reset " type = " SUBMIT " >允许仿真<html:reset>按钮的功能。当然,为了和Struts一起使用这个标签,需要将它嵌入到Strut-Faces <s:form>标签中。更多关于<h:commandButton>和<s:form>的细节参见第20章。
rewrite
这个标签解析并且呈现一个URL。所用的规则类似于<html:link>中所用的。不同于<html:link>的是,URL不是被嵌入到一个HTML <a>标签中,URL是单独呈现的。可以发现在调试时或用于脚本的时候这个标签是非常有用的。
1. 使用限制
必须指定action/ module、href、page或者forward属性。
2. 属性
· action/module、href、page或forward:用于指定一个URL。action/module属性对指定一个表单处理器。当然,action必须以一个“/”开始,并且如果想要指定一个模块,可以使用module属性。href可以是一个相对或者绝对URL。page是一个相对于模块的URL(因此也必须以一个“/”开始)。forward是一个全局转发的名称。
· anchor:该链接的一个可选的HTML锚。
· transaction:如果被设置为true,将附加当前的事务令牌到URL中作为一个请求参数。参看<logic:present>条目获得关于事务令牌的详细信息。
· paramname、paramproperty、paramscope和paramid:使用这些属性来创建一个请求参数。请求参数是附加到最后的URL之上的。三个属性中的第一个属性用于在当前请求或会话中定位一个对象。这个对象的toString()方法的返回值就是一个参数值。参数名称由paramId给出。
· name/property/scope:使用这些属性来创建多个参数。请求参数是附加到最后的URL中的。这些属性用于定位一个类型为的对象。Map的关键字是参数名,并且对应的值就是参数值。如果指定property属性,必须也指定name属性。
· useLocalEncoding:如果被设置为true,则告诉Struts针对当前HttpServletResponse使用什么字符编码。
3. 示例
这里是使用一个全局转发的简单例子:
呈现后的字符串将是success全局转发的真实URL。更多例子,参看<html:link>条目。
4. 对应物
无。
select、option、options和optionsCollection
select显示一个HTML选择列表。另一个option标签嵌套在它内部,以便为外围的select元素呈现选项。
· option:呈现为单个选项。它有一些可以使用来帮助对显示文字进行本地化的属性。
· options:显示一列选项,从一个JavaBean填充。
· optionsCollection:option的一个更合理化的版本。也显示一列从一个JavaBean填充的选项。
每个呈现得到的<option>都有一个值和标注。值是如果该选项被选择而提交的值。标注则是显示给用户帮助他们做出选择的文本。
1. 使用限制
select标签必须用在一个<html:form>标签之内,并且各种选项标签必须被嵌套在一个<html:select>标签内部。还有其他两个限制:
· property属性对select是必需的。
· value属性对是必需的。
2. 针对select的属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。除这些之外,还有几个专门针对select的属性:
· multiple:如果指定此属性(实际的值并不重要)将启动多重选择。如果该multiple属性被指定,基础属性必须是一个数组。就像<html:multibox>,如果想要检测一个没有被选择的条目,必须在ActionForm的reset()方法中设置基础属性为一个零长度的数组。更多细节参见<html:multibox>条目。
· size:一次显示的选项的数目。
3. 针对option的属性
option标签接受ren-attrs属性集,除此之外,下列属性是专门针对option的:
· value:被提交的值。这个属性是必需的。
· key:为选项指定标注的消息资源关键字。如果被忽略,标注就是嵌套在该option标签的标签体内部的文本。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。Locale属性指定一个可以用来在当前会话中查找Locale对象的关键字。bundle属性将会在条目<bean:message>中详细解释。可以使用这些属性来指定一个不同于当前用户场所的场所,或者一个不同于默认资源文件的消息资源文件。
4. 针对options的属性
option标签接受ren-attrs属性集,除styleId属性外。这个属性被省去是因为该options标签可以呈现为多个HTML <option>元素,而HTML标准禁止具有两个有相同id的元素。
有两种方式来为呈现后的元素指定值和标注:
· 指定collection/property/labelProperty属性:collection属性指定一个JavaBean集合的名称,每个JavaBean都持有单个<option>元素的值和标注。property属性是在每个bean之上调用的,用来为<option>获得值的getXXX()函数的名称。同样地,labelProperty属性是在每个bean上调用的,用来获得一个<option>标注的getXXX()函数的名称。如果labelProperty被忽略,<option>的值将被用做标注。
· 指定name/property和labelName/labelProperty属性:name和property属性对指定一个在任何作用域内的集合,可以从中获得每一个呈现后的<option>的值。如果仅仅指定property属性,那么ActionForm子类就是隐含的基础对象。同样地,labelName和labelProperty属性对指定一个集合,从其中可以获得每个呈现后的<option>的标注。如果仅仅指定labelProperty。那么ActionForm子类就是隐含的基础对象。如果既不指定labelName又不指定labelProperty,标注同值相同。
<html:options>剩下的属性是filter,如果设置为true,标签将过滤掉HTML保留字符(比如<、>或&)。默认值是true。
5. 针对optionsCollections的属性
optionsCollection是<html:options>的一个简化的合理化版本。类似<html:options>,optionsCollection标签也接受ren-attrs属性集中除styleId属性之外的属性。它也具有filter属性,像<html:options>一样。
optionsCollection假定每个呈现后的<option>的值和标注保存在一个JavaBean集合中。这个集合是使用name和property属性指定的。如果仅仅指定property属性,那么与外围的表单相关联的ActionForm子类就是隐含的基础对象。每个JavaBean被认为具有两个getXXX()函数,从中可以获得单个<option>标签的值和标注。
默认时,获得值的函数的名称是getValue(),获得标注的函数的名称是getLabel()。如果希望为每个函数指定不同的名称,那么可使用value和label属性。例如设置value="color"将意味着会调用getColor()函数来决定每个<option>的值。
6. LabelValueBean类
对于options和optionsCollection,需要具有获得值和标注的getXXX()函数的类。Struts具有一个实用类,名为. ,就是实际用于这个目的。它具有getValue()和getLabel()函数,可以立即用于optionsCollection中。代码清单C-1展示了可以如何使用这个类(或许在一个Action子类中)。
代码清单C-1 使用LabelValueBean类
7. 简单的性能优化
因为性能原因,应该保存和重用单个集合实例,而不是在每次填充Action的时候重新创建它。
可是,有时候,你的选择可能需要动态的和静态选项的混合。
这种情况的一个简单的解决方案是使用多个<html:optionsCollection>标签——一个针对来自于高速缓存的静态选项,另一些则引用动态创建的值-标注对。
即使在动态创建值-标注对的情况下,做一些优化也是可能的。最耗时的任务是创建新的LabelValueBean对象。如果可能的值-标注组合是有限的,可能想要将它们缓存在一个WeakHashMap中,WeakHashMap扮演着一个临时缓存。当然,以这种方式缓存JavaBean的好处可胜过计算关键字以从WeakHashMap中获得bean的性能损失。所以这个技术最好在已经有了一个可重用的关键字的时候才使用它。
国际化
使用JavaBean而不是Struts的消息资源机制意味着选项标注不能容易地进行本地化。一个简单的解决方案是为该集合使用一个定制类(参见代码清单C-2)(我们将使用一迭代器),并且使用LabelValueBeans来存储指向本地化的标注而不是实际的标注的关键字。
如从代码清单C-2中可见,在从消息关键字到实际标注的翻译的同时不创建不必要的对象需要一些技巧。
代码清单C-2 LocalizableIterator类
如代码清单C-2展示,LocalizableIterator在next()被调用的时候产生相同的对象,每次都使用一个不同的LabelValueBean进行配置。下面是可以如何在Action子类中使用这个类。记住,不同于代码清单C-1,LabelValueBean的基础集合(代码在清单C-2中由变量labelValuePairs给定)现在存储的是消息资源关键字而不是实际的标注:
1. 示例
可以在JSP代码中混合使用多个option/options/optionsCollection标签。下面就是一个例子:
或者,使用这个来启动多重选择:
记住,multiple属性的具体值并不重要——只要multiple属性被指定,Struts就假定基础属性是一个数组。
2. 对应物
JSF的<h:selectOneListbox>是单个选择表的对应物。<h:selectManyListbox>是多重选择表的对应物。
submit
这个标签显示一个按钮,如果被单击将导致外围的表单被提交处理。
1. 使用限制
这个标签必须用于一个<html:form>标签内部。
2. 属性
<html:submit>对前4个公共属性集(evt-attrs、acc-attrs、ren-attrs和struts-attrs)都是可以接受的。如果其值没有被指定,并且如果没有在它的标签体中呈现文本,那么按钮文字默认为“Submit”。
3. 示例
下面这个例子显示了3个提交按钮,所有的按钮的文本都是“Submit Me”。最后一个Submit按钮使用一个<html:bean>标签来本地化它的文本:
最后一种技术在表单中有多个提交按钮针对不同动作的时候特别有用。参看第17章关于LookupDispatchAction的小节找到更多细节。
4. 对应物
JSF的<h:commandButton id = "submit" type = "SUBMIT">允许仿真<html:submit>按钮的功能。当然,为了和Struts一起使用这个标签,需要将它嵌入到Strut-Faces <s:form>标签中。更多关于<h:commandButton>和<s:form>的细节参见第20章。
text/password
text表示一个一行的文本输入字段。password表示一个口令字段。两者之间唯一的差别在于,使用<html:password>标签,用户输入的字符将不会被显示出来;只有星号或其他的占位符被显示出来。
1. 使用限制
property属性是必需的。它必须是<html:form>标签的一个子标签。
2. 属性
全部的公共的属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。
除这些之外,还有几个专门针对text和password的属性:
· size:显示的字段的长度。如果省略,决定权便留给浏览器。
· readonly:如果被设置为true,意味着表单数据不能被编辑。
· maxlength:可接受的最大字符数。默认将允许无限的字符数。大多数浏览器忽略这个属性。
password标签具有一个额外的逻辑属性,称做redisplay,默认值为true,这将导致先前输入的口令(在表单因为验证错误而重新显示的时候)是否被重新显示为星号。不幸的是,实际的password是被嵌入到该页面的HTML代码中的。应该设置redisplay = false来防止口令从缓存的页面中泄密。
3. 示例
代码
指定一个针对当前表单bean上的email属性的文本输入字段。
则指定一个口令字段。
4. 对应物
JSF的<h:inputText>是<html:text>的一个对应物,但是需要将它包围在Struts Faces之内,以便关联的表单bean能够被提交的值填充。
textarea
这个标签表示一个多行的文本输入字段。
1. 使用限制
property属性是必需的。它必须是<html:form>标签的一个子标签。
2. 属性
全部的公共属性集(evt-attrs、acc-attrs、ren-attrs、struts-attrs、init-attr和新的err-attrs)都是可接受的,并且都有其通常的意义。有几个属性专门针对textarea:
· cols/rows。要显示的列(cols)或者行(rows)的数目。如果两者被忽略,则由浏览器决定。
· readonly。如果为true,意味着表单数据不能被编辑。
3. 示例
代码
指定一个针对当前表单bean上的memo属性的textarea输入字段。
4. 对应物
JSF的<h:inputTextarea>是<html:textarea>的一个对应物,但是需要将它包围在Struts Faces的<s:form>标签之内,以便关联的表单bean能够被提交的值填充。
xhtml
这个标签将导致当前页面中的Struts标签按照XHTML 规范呈现。这本质上是HTML的一个遵循XML的版本。读者应该知道浏览器可能会回避XHTML元素,如<input/>而不是HTML的<input>。
1. 使用限制
如果使用一个JSP include,注意这个标签是不能继承的。必须将这个标签放到想要呈现为XHTML的各个JSP和JSP碎片中。
2. 属性
无。
3. 示例
只需要在页面的开始处放置<html:xhtml/>。
4. 对应物
无。
Bean标签库
Bean标签库具有读取JavaBean属性的标签和写出文本的标签。使用Bean标签而不是在JSP中进行硬编码有两个原因。第一个是允许进行国际化。第二是避免使用scriptlet。
表C-10给出了Bean库中的标签的概要,它基于Apache的文档。Apache许可证的副本可以参见 。
表C-10 Bean标签库的概要
标 签
用法/注解
message
根据给定的关键字输出静态文字
write
输出指定的JavaBean属性的值
cookie/header/parameter
每一个都基于指定的cookie/header/parameter/variable的值暴露一个脚本变量
define
每一个都基于指定的JavaBean的值暴露一个脚本变量
page
每一个都基于指定的页面—作用域变量的值暴露一个脚本变量
include
允许调用一个JSP或全局转发或URL,并且使得结果响应数据可以作为一个变量访问。被调用页面的响应不会被写出到响应流之中
resource
允许从当前Web应用程序读取任何文件并且将其暴露为一个字符串变量或者一个InputStream
size
定义一个新的JavaBean,在一个指定的Collection/Map /数组中包含元素的数目
struts
将指定的Struts内部配置对象暴露为一个JavaBean
Bean标签库的Struts-EL标签
在Bean库中只有下列标签具有EL使能的版本:include、message、page、resource、size和struts。
注意
EL使能的标签是指那些允许使用EL表达式的标签。具体例子参见第10章。
cookie/header/parameter
每一个都基于指定的cookie/header/parameter/variable的值暴露一个脚本变量。
1. 使用限制
id属性和name属性是必需的。
2. 属性
· name:需要取得的cookie/header/parameter的名称。
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问cookie/header/parameter的属性。
· value:万一给定名称的cookie/header/parameter不能被找到而需要返回的默认值。
· multiple:指定具有相同名称的多个cookie/header/parameter如何被处理。这个属性的实际值并不重要。如果multiple属性被设置,那么通过id暴露的变量便是一个对应类型的数组(Cookie []/String []/String [])。如果multiple属性不存在,那么第一个发生的cookie/header/parameter就会被绑定到暴露的变量。
3. 示例
考虑下面的URL:
下面就是如何在请求URL上面暴露名为command的参数:
如果有不只一个名为command的参数,例如:
可以这样访问它们:
其他的header和cookie标签具有类似的例子。
4. 对应物
JSTL <c:set>是这个标签的替代。
下面是如何在没有指定multiple属性的情况下将<c:set>作为此标签的对应物。变量名为myVar *,对应的cookie/header/parameter的名称都是myAttr。
如果multiple属性被指定,那么可以使用下列方式之一:
注意,这里还使用了一个<c:remove>标签来删除一个声明了的变量。
define
这个标签基于来自一个给定的字符串,或另一个JavaBean的数据暴露一个变量。scriptlet及其他标签可以像访问任何其他的变量一样访问这个暴露变量。这可能好像没有什么用处,但是它的确有用。参见具体的例子。
也请参考cookie/header /parameter和page条目,其中有相关的标签。
1. 使用限制
id属性是必需的,并作为要暴露的变量的名称。也需要指定name/property/scope或value,或者将暴露的变量的值嵌入到<bean:define>标签的标签体内部。还有,只可以一次定义一个变量。试图在同一个页面中定义一个同名的新变量将导致抛出异常。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。
· name/property /scope:这些属性使用一个给定的name和可选的property和scope属性来定位一个被暴露的对象。如果没有指定scope,将在所有作用域中查找给定名称的对象。
· value:要暴露的字符串值。这样将通过id属性暴露的变量绑定到value属性指定的字符串。
· toScope:在其上保存新变量的作用域。可以是page、request、session或application。
· type:使用id属性暴露的变量的全限定类名。如果未被指定,在指定value属性的时候将同时使用。要使用嵌套技术也会有提示(见示例),如果使用name/property/scope的方式,隐含的类名是。
3. 示例
下面是可以使用<bean:define>来暴露一个字符串或变量的例子:
在最后一个例子中,如果()返回null,那么将抛出一个异常。否则,myVar5等于()在其被调用时的值。
如果与Struts EL标签一起使用,可以使用<bean:define>来帮助本地化验证(见第12章),回想一下,在第12章的对本地化验证的处理,我们解释说可以使用嵌入本地化格式字符串到表单数据中的技巧来解决(参看代码清单12-3)。Action将被用于填充隐藏字段。填充该隐藏字段的更优雅的方式是使用<bean:define>和<html-el:hidden>,就像这样:
指向的消息是日期格式,当然,这是被Struts自动本地化的。不需要任何Action子类!
4. 对应物
JSTL <c:set>可用于替换<bean:define>。前面的例子移植到<c:set>可能是:
最后一个例子是相似的:
include
这个有趣的标签允许调用一个外部的JSP或全局转发或URL,并且将结果响应数据作为一个变量访问。被调用页面的响应不会写出到响应流。如果该暴露的变量是用<bean:write>显示的,接收到的输出是经过HTML编码的(“<”被替换为“& It;”,等等)。
1. 使用限制
必须指定id属性和forward、page或者href属性之一。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。结果变量是页面作用域的。
· forward:要调用的全局转发的名称。
· page:要调用的当前Web应用中的JSP页面的名称。这个名称是相对于模块的,并且需要一个“/”前缀。
· href:外部页面的的绝对URL,例如
· anchor:被调用页面的HTML锚的名称。
· transaction:如果被设置为true,则会在响应中包含事务令牌。参见<logic:redirect>条目中的说明。
3. 示例
这个例子读取给定的外部页面,然后显示实际的内容。接收到的HTML都是经过编码的:
4. 对应物
最接近的对应物是JSTL的<c:import>,它调用一个URL并且暴露接收的数据为一个String或者一个Reader。前面的例子可以轻易地转变为使用JSTL:
注意,还可以使用嵌套<c:param>标签在接收数据上执行参数替代。
message
这个标签显示一个国际化了的消息。最多可以指定5个替代参数。
1. 使用限制
必须指定key属性或者name/property/scope组合。
2. 属性
· key:要显示的消息资源的关键字。如果locale/bundle组合没有被指定,那么默认消息资源文件和用户的当前场所将被用来决定显示哪个消息资源。
· name/property/scope:这些属性被用来基于一个具有给定的name和可选的property和scope属性的对象来导出一个关键字。如果没有指定scope,将在所有作用域中查找给定名称的对象。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。locale指定一个可用于查找存储于当前会话中的Locale对象的关键字。bundle属性将在下面的小节中详细解释。
· arg0/arg1/arg2/arg3/arg4:这些分别是第一个、第二个、第三个、第四个以及第五个替代参数的值。
3. 使用多重消息资源文件
Struts允许声明多个消息资源文件(也就是说,对同一个场所有多个文件。每一个这样的消息资源文件被命名为一个唯一的名称,并在Struts标签中使用bundle属性来引用)。默认消息资源文件没有名称,并且它是唯一的,也就是说如果bundle属性没有被指定,就将使用它。
你应该知道使用多重的消息资源文件有一些问题:
· 有报告说与Validator框架一起使用会有问题。
· 它让维护更加困难。这是因为除指定关键字之外,必须指示bundle名称(如果它不是默认的那个的话)。如果后来决定将一个消息从一个文件移动到另一个文件中(如果想要调整一个应用程序以确保显示的消息或提示的一致性,这就会很常见),那么必须修改每个使用那些特殊消息的标签的bundle属性值。
所以应该尽可能地避免使用这个特征。
一种可选的方法是对关键字使用一种命名约定,比如点号命名约定(例如,. )。笔者在本书中就对消息关键字使用了这种约定。这能够创建分离的名字空间,因此排除了使用多个消息资源文件的必要。
现在应该知道使用多个消息资源文件的危险了。下面是可以如何在文件中声明多个消息资源文件:
在这个例子中,第二个消息资源文件是,并且被保存在与默认的文件的同一地点(也就是说,在/WEB-INF/classes/中)。
为了从该默认文件中显示一个提示,可使用
为了从第二文件中显示一个提示,可使用
额外的bundle属性告诉Struts使用哪个消息资源文件。
4. 示例
下面是如何显示一个消息的例子:
这里是如何使用其toString()方法返回关键字的JavaBean的例子:
这里是如何使用其属性给出关键字的JavaBean的例子:
这个例子调用()并且将其用做消息关键字。如果必要将在返回值上调用toString()方法。如果该消息具有替代参数,例如:
可以使用下面的代码来执行替代(使用EL):
5. 对应物
在JSTL和JSF中都有对应物。对于JSTL,可以使用格式化库:
这段代码片段是最后一个例子使用对应物的情况,使用了一个替代参数。如果使用JSF,可以很方便地使用Struts-Faces库(参见第20章)来暴露默认消息资源文件:
这和前面的JSTL例子是等价的。最后,还有一个来自Struts-Faces集成库的<s:message>标签。
page
这个方便的标签将来自于页面上下文中的对象暴露为可以通过scriptlet或定制标签访问的变量。
PageContext对象是当前页面的所有状态的储存库。这包含在第2章描述过的会话(HttpSession)和请求(HttpServletRequest)中。还有一些:
· application:对象,通过调用- Context()来获得。
· config:对象,通过调用()来获得。不要将其与Struts的内部配置对象搞混淆。
· response:与此页面关联的HttpServletResponse对象。
应该参考最新的servlet参考文档(或者在Google上搜索类名来找到相关JavaDoc),以获得有关它们的更多详细信息。
1. 使用限制
id属性和property属性都是必需的。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。这个属性是必需的。
· property:该属性的值是application、session、request、config或response,用于从页面上下文获得关联的对象。这个属性是必需的。
3. 示例
代码片断
将与外围的页面相关联的会话对象(HttpSession)暴露为一个名为myVar的bean。另一个页面上下文对象是以同样的方式被暴露的。
4. 对应物
JSTL的<c:set>可用于替换<bean:page>。我们来看一些例子。为暴露应用程序,使用这个代码:
为了暴露会话,使用这个:
为了暴露请求,使用这个:
为了暴露配置对象,使用这个:
为了暴露响应,使用这个:
应该注意到JSTL隐含的对象sessionScope和是不相同的。前者是一个包含关键字/值对的Map,后者是实际的HttpSession对象,可以读取它的属性。
resource
resource允许从当前Web应用程序读取任何文件并且将其暴露为一个字符串变量或者一个InputStream。参见<bean:include>。
1. 使用限制
id属性和name属性是必需的。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。这个属性是必需的。
· name:要加载资源的模块相对的名称。
· input:如果这个属性被指定(实际的值并不重要),那么该暴露的变量具有InputStream类型,否则它是String类型。
3. 示例
说实在的,很难看到这个标签如何有用,除非使用其他可以读取和解析InputStream的定制标签。下面是使用一假定的RSS源(/,其中包含RSS标记)的一个例子,以及一个假定的用来显示RSS输出的<rss>定制标签例子:
4. 对应物
最接近的对应物是JSTL的<c:import>,它调用一个URL并且暴露接收到的数据为一个String或者一个Reader。前面的例子可以轻易地转变为使用JSTL:
size
这个标签将一个给定的Collection或者Map或者数组的大小暴露为一个变量(整数类型),可以从scriptlet或定制标签访问到。
1. 使用限制
id属性是必需的,并且必须指定想要测量大小的数组/ Collection/Map,使用collection属性或者一个name/property/scope组合。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。这个属性是必需的。
· name/property/scope:这些属性被用来定位Collection/Map/数组,基于可选的属性和作用域。如果没有指定scope,将在所有作用域中查找给定名称的对象。
· collection:这个是name/property/scope组合的一个非常方便的替换物。使用scriptlet来计算这个属性的值,例如:
这个属性后面的基本原理将在<logic:iterate>条目中解释。
3. 示例
下面是暴露一个给定集合的大小的简单例子:
4. 对应物
可以连同JSTL length函数使用JSTL的<c:set>:
记住声明JSTL函数标签库。
struts
这个标签暴露一个Struts全局转发,或表单bean或表单处理器(该表单处理器的ActionMapping)为一个变量,可以通过scriptlet及其他标签进行访问。如果想要JSTL能够访问Struts的内部变量,这是很有帮助的。
1. 使用限制
id属性是必需的。还必须指定forward、formBean或mapping属性。
2. 属性
· id:要暴露的变量的名称。scriptlet及其他定制标签将能够使用这个名称来访问该新变量。这个属性是必需的。
· forward:要暴露的全局转发的名称。
· formBean:要暴露的已经声明的表单bean的名称。
· mapping:要暴露的表单处理器的名称。
3. 示例
考虑这段代码:
下面是暴露全局转发的方式:
以及表单bean:
以及表单处理器:
4. 对应物
无。
write
这个标签将指定的bean属性输出为响应流。它允许对给定的bean属性进行一些格式化。
1. 使用限制
name属性是必需的。
2. 属性
· name/property/scope:这些属性被用来基于给定的name 和可选的property 和scope 来定位JavaBean。如果没有指定scope,将在所有作用域中查找给定名称的对象。
· ignore:如果被设置为true,则一旦命名的JavaBean没有找到,则失败,什么也不会发生。默认值(false)导致一个异常被抛出。
剩下的属性用来格式化bean的属性:
· filter:如果设置为true,将导致属性的字符串值是HTML编码的。例如,符号(&)将被编码成& amp;而>将被编码成& gt;默认是true。
· format/formatKey:这两者都指定一个用于格式化bean的属性的格式化字符串。format将按照字面使用其值来作为格式化字符串。而formatKey则将它的值作为一个关键字从消息资源文件中查找实际的格式化字符串。除非locale/bundle组合被指定,当前用户的场所以及默认消息资源束将被使用。
· locale/bundle:这些属性用于指定一个不同的场所对象或消息资源文件。Locale属性指定一个可以用来在当前会话中查找Locale对象的关键字。bundle属性将会在条目<bean:message>中详细解释。可以和formatKey一起使用这些属性来指定一个不同于当前用户场所的场所,或者一个不同于默认资源文件的消息资源文件。
3. 示例
代码
将显示由myString引用的字符串。
将显示()的值。
将显示等于的myFloat为。
将格式化由myCalendar表达的日期为dd/mm yyyy。例如20 Feb 2006将被显示为20/02/2006。
将使用消息关键字的值作为格式化字符串。
4. 对应物
可以使用JSTL的<c:out>来显示一个bean的属性:
将显示()的值。为了格式化该输出,可以使用JSTL的格式化标签库:
相当于前面给出的数值格式化的例子,或者:
JSTL的格式化标签库具有许多格式化字符串、日期、货币以及数值的变化。
如果你还感兴趣想深入了解,应该参考最新的JSTL规范。
最后,Struts-Faces集成库中的<s:write>标签是另一个对应物。
Logic标签库
Logic标签库提供条件处理、循环以及流控制的标签。
· 条件处理:equal/notEqual,empty/notEmpty,greaterEqual/lessEqual/greaterThan/ lessThan,match/notMatch,messagesPresent/messagesNotPresent以及present/ notPresent。
· 循环:iterate标签。
· 流控制:forward和redirect标签。
所有这些标签,除了涉及到流控制的那两个,都有JSTL对应物,所以应该尽可能地使用JSTL版本。
公共属性集
对于Logic标签库,有两个公共的属性集。第一个,我们称做基础对象属性集(或简称base- attrs),列于表C-11中,以及属于对应的标签所适用于的JavaBean对象。
表C-11 base-attrs属性集
属性名称
用 法
name
基础对象的名称。如果这个属性被忽略,那么隐含的基础对象(如果有)会被使用。如果该标签被包围在一个<html:form>中,隐含的基础对象将是与该表单关联的表单bean
property
基础对象上的属性,其值被用于标签的功能。例如标签是一个比较标签,那么基础对象上的属性的值便被用于比较。这假定基础对象上有一个对应的getXXX()函数
scope
表示一个作用域,将在其上根据给定的name属性查找对象。如果scope没有被声明,那么要根据name 属性指定的名称查找所有作用域。有效的作用域是page、request、session和application
一些标签允许使用来自其他来源的值(也就是说,除了基础对象上的属性之外)来完成它们的工作。这些扩展Property属性(exprop-attrs)列出在表C-12中。
表C-12 exprop-attrs属性集
属性名称
用 法
cookie
要使用的cookie的名称
header
要使用的HTTP请求头变量的名称。该名称的匹配是忽略大小写的
parameter
要使用的URL请求参数的名称。如果不只一个,将使用第一个
选择器属性
Logic库中的许多标签都使用选择器属性。这些属性被用于选择对象或属性来执行该标签的功能。选择器属性是cooki、header、name/property和parameter。
Struts将按这个次序询问这些属性。例如,如果指定了cookie和parameter,只有cookie属性被用于执行该标签的任务。
注意,name/property属性在这里被视做一对。也就是说如果指定了name,可以同时可选地指定property属性。如果它们的作用是选择器属性的话,不能仅仅单独指定property,必须同时指定name。可以参考每个标签的说明文档来区分是否是这种情况。
针对Logic标签库的Struts-EL标签
只有下列标签在逻辑库具有EL使能的版本:forward、iterate、match/notMatch、messages- Present/messagesNotPresent、present/notPresent以及redirect。其他标签具有更简单的JSTL对应物。
注意
EL使能的标签是指那些允许使用EL表达式的标签。参看第10章的例子。
empty/notEmpty
empty将在指定的属性或基础对象为null的时候,即一个零长度字符串,或一个空的集合或Map的时候,有条件地执行它的标签体。如果property属性没有被指定,测试将基于name属性给定的基础对象进行。
notEmpty是empty的逆命题。
1. 使用限制
name属性必须指定,即使嵌套在一个<html:form>内部。
2. 属性
只有base-attrs属性集适用。
3. 示例
以下例子展示了如果MyCollection是空的,将使用<logic:empty>标签来有条件地处理嵌套的<bean:write>标签。
下一个例子说明了property属性的使用:
<bean:write>只有当getEmail()函数返回null,或一个零长度字符串时才会被执行。还可以使用作用域变量来指定在其中查找bean的作用域:
在前面的例子中,如果MyBean可以在请求作用域中找到,<bean:write>将在基础对象之上被调用。
4. 对应物
可以轻易地使用JSTL的<c:if>或<c:choose>... <c:when>来创建empty和notEmpty的对应物。例如使用<c:if>,前面的例子将成为:
和
必须使用JSTL隐含的对象(requestScope、sessionScope等)来指定一个作用域:
equal/notEqual
equal检查给定的属性(或扩展属性)是否等于一个给定值。如果是这样的话,equal标签的标签体便会被执行。
notEqual是equal的逆命题。
1. 使用限制
value属性是必需的。必须同时指定一个选择器属性(参见本节开始的定义)。
2. 属性
base-attrs和exprop-attrs属性集都是接受的。还有一个额外的value属性,它是属性或扩展属性将要与之比较的一个常数值。
3. 示例
以下例子展示了,如果变量client等于“Joe”,<logic:equal>标签将会处理嵌套的<bean:write>标签。
下一个例子说明parameter属性的使用。
标签体部分只有在请求URL中具有一个值为Susan的名为username的参数才会被执行。如果有不只一个这样的参数,URL上第一个遇到的参数将被使用。
还可以使用scope变量来指定在其中查找一个bean的作用域。
在这个例子中,如果在会话作用域中有一个名为MyBean的bean,并且它的getEmail()函数返回一个等于joey@的值,<bean:write>便会在基础对象之上被调用。注意,如果MyBean值为null,或者不具有一个getEmail()函数,则会抛出一个异常。
4. 对应物
可以轻易地使用JSTL的<c:if>或<c:choose>... <c:when>来创建equal和notEqual的对应物。例如使用<c:if>,前面的例子将成为:
下一个例子说明parameter属性的使用。
还可以使用scope变量来指定在其中查找一个bean的作用域。
此外还要注意,不同于那些仅允许一个常数值的Struts标签,JSTL对应物没有这样的限制。下面是将一个变量与另一个变量比较的例子(用Struts标签是不可能实现这个的,因为要与之比较的值必须是常量,当然,除非你乐意使用scriptlet):
forward
这个标签导致页面被转发到指定的全局转发(参见第9章和第17章)。此标签没有标签体。参见<logic:redirect>。
1. 使用限制
name属性是必需的。
2. 属性
name属性是要使用的全局转发的名称。
注意
如果希望转发到一个Tiles定义,可以从一个Action子类中进行,然后它又被暴露为一个全局转发。
3. 示例
考虑在中声明的全局转发:
那么,转发
将导致页面被显示。同样地,转发
将导致表单处理器被调用,可以使用它来加载一个Tiles定义。
4. 对应物
无。
greaterEqual/lessEqual/greaterThan/lessThan
greaterEqual是一个有条件标签,只有在给定的属性(或扩展属性)大于或等于由value属性给出的常数值的时候,其标签体才会被执行。本组中的其他标签也是类似定义的。
注意,如果值不是一个数值,它会被解释为一个字符串,并且会执行字符串之间的比较(使用Java的标准字符串比较)。
1. 使用限制
value属性是必需的。必须同时指定一个选择器属性(参见本节开始的定义)。
2. 属性
base-attrs和exprop-attrs属性集都是接受的。还有一个额外的value属性,它是属性或扩展属性将要与之比较的一个常数值。
3. 示例
下面的例子展示了使用<logic:greaterThan>标签来在变量hits大于或等于10的时候处理嵌套的标签(没有具体展示出来)。
下一个例子说明cookie属性的使用。
只有当称做logintries的cookie大于3的时候,<bean:message>才会执行。
4. 对应物
可以轻易地使用JSTL的<c:if>或<c:choose>...<c:when>来创建这些标签的对应物。例如使用<c:if>,前面的例子将成为:
下一个例子说明cookie属性的使用:
还要注意,JSTL对应物不同于仅容许一个常数值的Struts标签,它没有这样的限制。
iterate
<logic:iterate>标签可用于在Collections、Map、Enumerations、数组或Iterator(都被认为是可迭代的对象)之上进行迭代。嵌套在一个<logic:iterate>之内的标签(或静态文字)将被执行为JSP的响应流(即写出到最终的HTML页面中)。
1. 使用限制
id属性是必需的。此外还必须指定可迭代的对象(使用name/property属性或者collection属性)。
2. 属性
iterate标签使用base-attrs来指定要对其进行迭代的Collection/Map/Enumerations /数组/Iterator的基础对象。除了这些,还有其他几个可以使用。
· collection。name/property组合仅允许在可以被读取为JavaBean属性的可迭代对象之上迭代。这可以是十分限制性的。例如:
意味着调用函数:
以决定可迭代的对象。然而,许多Java类不使用JavaBeans的getXXX()约定,所以对它们需要使用一个不同的方法。解决方案是随一个scriptlet一起使用的collection属性。
· id:指定从可迭代的对象中读出的单个元素的名称。
· indexId:当前索引,从零开始。
· length:从可迭代对象读取的元素的最大数目。如果不存在,所有的元素都会被读取。
· offset:从可迭代的对象中返回的第一个元素的索引。例如,如果该可迭代对象是一个数组[a,b,c],使用offset = "1"将导致仅读取b和c。注意,偏移量是零基的,就像Java中的约定一样。
· type:从可迭代对象中读取的元素的全限定类名。如果元素不匹配这个类名,将会抛出一个ClassCastException异常。
3. 示例
这就是基本用法:
使用collection属性的用法:
以及使用indexId属性来显示当前迭代编号的用法:
4. 对应物
JSTL的<c:forEach>是<logic:iterate>的最好替代。这里是使用JSTL前面的那个例子:
第二个例子不需要collection属性:
最后可以这样来暴露迭代编号:
match/notMatch
match标签将在一个在给定属性(或扩展属性)包含作为一个子串的value属性的时候执行其标签体的条件处理标签。notMatch是match的逆命题。
1. 使用限制
value属性是必需的。必须同时指定一个选择器属性(参见本节开始的定义)。
2. 属性
base-attrs和exprop-attrs属性集都是可接受的,并且具有它们的通常意义。除这些之外,还有两个额外的属性:
· value:属性或扩展属性将要匹配的一个常数子串。例如,如果属性或扩展属性等于字符串“Visit Zimbabwe”,那么value="im"将导致一次匹配,而value="Zic"则不会。
· location:此属性值可以取值start或者end,指定在源字符串内部可以从哪里发生匹配。如果忽略,匹配可以从任何地方开始。
3. 示例
下面是查找一个具有.sg后缀的电子邮件地址的简单例子:
或可以询问HTTP请求头:
4. 对应物
可以轻易地使用JSTL的<c:if>(或<c:choose>...<c:when>)以及JSTL函数创建这些标签的对应物。(这是一个标准JSTL函数库。要使用它,必须声明JSTL函数标签库。)例如,使用<c:if>的前面的例子将是:
和
5. messagesPresent/messagesNotPresent
messagesPresent是一个如果给定的消息或错误信息存在于当前请求之中的时候,就执行其标签体的条件处理标签。messagesNotPresent是messagesPresent的逆命题。
请注意以下术语:
· “错误消息(Error messages)”是保存在一个ActionMessages/ActionErrors实例中的ActionMessage实例,ActionMessages或ActionErrors实例又在请求中保存在关键字_KEY之下。
· “消息(Messages)”是保存在一个ActionMessages/ActionErrors实例中的ActionMessage实例,ActionMessages或ActionErrors实例又在请求中保存在关键字_ KEY之下。
例如,ActionForm的validate()函数可能返回一个ActionErrors实例,其中包含一个或多个ActionMessage 实例。这些ActionMessage实例被按关键字保存,如在第6章以及第7章所见。关键字被作为对应的错误信息/消息的名称。
错误消息和消息都可以使用<html:errors>显示出来,或者使用<html:messages>进行迭代。
6. 使用限制
7. 属性
有3个属性:name,property和message。注意,name和property属性不具有它们通常的意义。反之,取决于这些属性的设置,将进行以下检查:
· 如果没有指定任何属性,messagesPresent简单地检测是否在当前请求中有错误消息存在。如果有错误消息,便执行它的标签体。设置message = " true "将导致messagesPresent检查所有消息。
· 如果property属性被指定,messagesPresent将检测是否有具有该名称的错误消息。再次说明,设置message = "true"导致检查所有适当的消息。
· name属性允许你在请求之中,根据_KEY或_KEY之外的关键字寻找错误消息/消息。注意,如果指定了message属性,name属性会被忽略。
· 如果name属性被指定,那么即使一个String或者String数组在请求中也会导致匹配。
最好以例子来说明不同的组合。
8. 示例
最简单的例子是测试错误消息是否存在:
或者可以测试一个特定的错误信息:
如果Action提交了消息,也可以测试它们:
并且可以在请求中基于一个特定的关键字寻找错误消息或者消息,或者String或者String数组。
9. 对应物
无。当然,有一些技巧可以让你同时使用JSTL的<c:if>和scriptlet。
present/notPresent
present会检查请求作用域,是否在指定属性或者扩展属性之下有一个对象存在。如果该对象存在,该标签的标签体会被执行。notPresent是present的逆命题。
1. 使用限制
必须指定一个选择器属性(参见本节开始的定义)或者user或者role属性。
2. 属性
base-attrs和exprop-attrs属性集都是可以接受的,并且具有它们通常的意义。如果property属性被指定,present会检查出返回值不是null。
除此之外,还有user和role属性。这取决于基础的servlet认证一个用户的技术,以及为该用户指定一个或多个角色。关于这些是如何执行的超过本书范围之外,因此如果你还感兴趣,应该参考最新的servlet参考文档。user属性指定当前请求的远程用户的名称。role属性是角色的一个逗号定界字符串。如果任何一个这些角色是当前用户的一个有效角色,present会执行其标签体。
3. 示例
最简单的用法是检查请求上一个对象是否存在:
类似地,property属性的使用是为了保证给定的属性不是null。
你还可以检查当前经过认证的用户名:
或者该当前认证用户具有任何指定的角色:
4. 对应物
可以轻易地使用JSTL的<c:if>或<c:choose>...<c:when>来创建这些标签的对应物。例如使用<c:if>,前面的例子将成为:
不幸的是,最后一个检查角色的例子没有JSTL对应物。然而有一个JSF安全扩展可以简洁地处理这些情况。如果感兴趣,请参考。
redirect
这个标签执行一次页面重定向。该标签没有标签体。参见<logic:forward>。
1. 使用限制
必须指定forward、href、action或者page属性来指定重定向到的基础URL。
2. 属性
有两个主要的属性集。第一个属性集指定重定向到的页面的基础URL。有4种方式来完成这个任务。
· forward:重定向到的全局转发的名称(例如,forward = "login")。
· href:重定向到的原始的URL(例如,href = "http:/")。
· action:重定向到的表单处理器的名称(也就是说,动作映射)。这必须以“/”开头,因为它相对于默认模块(例如action = "/Logoff")(关于模块参见第17章)。
· page:重定向到的当前Web应用程序中的Web页面的路径。这个路径相对于Web应用程序的基础文件夹。路径必须以“/”开头(例如,page = "/")。
redirect也允许在重定向URL上指定参数:
· anchor:让你指定一个锚的名称。锚是标准的HTML,可为较长的网页标识段落,以便于导航。
· name/property/scope:这些属性用来在请求或者会话上定位一个Map实例。该映射的关键字是参数的名称并且值是对应的值。在值是一个数组的情况下,多个参数会被写出到URL中,其中每个都具有相同名称但是具有不同的值。如果创建了超过一个URL参数,可以使用这三个变量的组合。
· paramname、paramproperty、paramscope和paramid:第一个用来在当前请求或者会话上定位一个对象。如果这个对象不是一个数组,它的toString()方法将被调用并且其返回值是一个参数值。如果该对象是一个数组,那么正在创建的是多个同名的但是不同值的参数。参数的名称是由paramId给出的。
剩下的属性是useLocalEncoding和transaction。
· useLocalEncoding:如果被设置为true,告诉Struts对当前HttpServletResponse使用什么字符编码方案。
· transaction属性则需要一些详细描述。
事务令牌
Struts有一种防止表单被重复提交的机制。如果用户接二连三地单击表单的提交按钮,重复提交就会发生。通常,Struts会将这种情况处理为两个单独的提交。当然这是一个错误。对这个问题的标准解决方案是使用一个事务令牌。
必须使用两个Action子类,第一个Action子类在表单被请求的时候被激活。它将在请求和会话中放置一个唯一的字符串。这个唯一的字符串就是事务令牌。Action具有函数
来为你做这件事情。这个函数自动地产生事务令牌并且将其以适当的关键字放置在请求和会话中。这个Action子类的execute()函数的一个简单的例子如下:
第二个Action子类是在表单数据被用户提交时处理表单数据一次的动作。它的execute()如下:
函数isTokenValid(request,true)会进行检查,以确保在该请求上的事务令牌与在会话中的令牌相匹配。一旦该检查完成,它便销毁该令牌在会话上的副本。这意味着如果用户第二次单击该提交按钮,在会话上将没有副本,导致isTokenValid()返回false。
然而,你应该知道,前面小节所述的简单的解决方案具有一个巨大的不足:发送回到用户的错误页面(重复提交)可能使得他认为表单数据根本没有被处理!小心构造的错误信息可能会有帮助,但是你仍然不可能使用户到达真实的成功页面。更完善的解决方案可以同时解决这样的用户交互问题。回到transaction属性,如果它被设置为true,那么在请求上的事务令牌会被作为一个URL参数发送。
1. 示例
下面是一个使用全局转发名称的简单的重定向:
接下来是一个添加单个URL参数的例子。参数的名称(paramId)是email-address。参数的值是由调用()来决定的:
下面是基于一个Map来添加多个URL参数的方法,Map是由调用()来得到的,它又位于会话作用域内:
2. 对应物
无。没有单一的JSTL标签或者JSF标签来执行<logic:redirect>的所有功能。
nested标签库
nested标签库允许相对于一个对象来应用标签。可以使用嵌套属性仿真完全相同的功能(参见第10章的详细解释)。
不幸的是,对于一名程序员来说,嵌套标签库可能会感到好像一个临时凑合的鸡肋。例如,假定想要输出().getMyPropertyB()的内容。
可能期望能够这样做:
nested标签库提供了<bean:write>以及许多其他标签的替代。所以执行该任务的正确代码是:
<bean:write>的替代是<nested:write>。大部分嵌套标签库由替代标签组成。这些都是它们在其他标签库中的对应物的严格复制。
· HTML标签的替代:checkbox、errors、file、form、hidden、image、img、link、messages、multibox、options、optionsCollection、password、radio、select、submit、text和textarea。
· Bean标签的替代:define、message、size和write。
· Logic标签的替代:empty、equal、greaterEqual、greaterThan、iterate、lessEqual、lessThan、match、messagesNotPresent、messagesPresent、notEmpty、notEqual、notMatch、notPresent和present。
因为这些标签是对其正本的严格复制,这里不再重复它们的功能。读者可以参考本附录中的原始标签。除了这些替代标签之外,嵌套标签库还有3个自己的标签需要说明。随后的小节就是完成这个任务。
针对nested标签库的Struts-EL标签
针对nested标签库没有Struts-EL标签。
注意
EL使能的标签是指那些允许使用EL表达式的标签。参看第10章的例子。
nest
这个标签允许嵌套被上升一级。位于当前<nested:nest>标签内部的所有的替代标签将取得和本标签的property属性指示的它们的基础对象的值。
1. 使用限制
无。但是明显地,为了能够运行,需要指定property属性。
2. 属性
仅仅有一个属性:property。它指示在当前隐含的基础对象上的属性,从该对象起,所有的子嵌套标签都会使用它作为基础对象。
3. 示例
假定想要在一个<html:form>内,比方说使用<bean:write>访问一个嵌套属性:
还可以这样使用<nested:nest>和标签:
在这两个代码片断中,隐含的基础对象都是由包围的<html:form>决定的。基础对象正好是与该表单关联的表单bean的实例。如果想要改变基础对象,必须使用<nested:root>。
4. 对应物
无。
writeNesting
这个标签用来将当前嵌套层次输出到响应流(即呈现后得到的HTML页面),或者使其作为一个页面作用域变量来访问。
1. 使用限制
无。
2. 属性
这个标签具有3个属性。
· property:这个属性的值将原样地附加到嵌套层次的结尾,用一个点作为前缀。
· id:当id被指定时,嵌套级不写出到最后的HTML页面,而是暴露为一个页面作用域字符串变量,id的值充当名称。
· filter:这个属性取值为true或者false。如果为true,那么嵌套层次将被编码。例如,&号(&)表现为& amp;不管Apache联机文档怎么说,URL编码不会执行,例如,空格不会被编码为%20%,等等。
这些属性最好以JSP例子来说明。
3. 示例
仅当与<nested:nest>标签一起使用时,使用writeNesting才有意义,如下面的例子:
在这个例子中,显示的HTML将包含文本:
如果我们使用了<nested:writeNesting id = "dummy"/>,那么输出将会是为空。这是因为输出没有被显示在页面中,而是创建了一个名为dummy的页面作用域变量。要显示它,需要使用一个嵌入到与定义该变量的<nested:writeNesting>相同嵌套层次的scriptlet。例如:
注意,如果将scriptlet放在不同的嵌套层次上,会得到一个错误:
最后,propertyattribute只是简单地附加给定的值至嵌套层次的结尾。所以代码片断:
在HTML页面上显示为:
4. 对应物
无。
root
这个标签用来指定一个基础对象。
使用root来指定一个与当前基础对象(同<html:form>标签内部)不同的基础对象,或者如果该对象还不存在,则定义一个基础对象(通常在<html:form>之外)。
1. 使用限制
无。但是明显地,为了能够运行,需要指定name属性。
2. 属性
仅仅有一个属性name,它是在当前请求上的JavaBean的名称。这个bean被用做由<nested:root>包围的所有的嵌套标签的新的基础对象。
3. 示例
假定想要在一个<html:form>内,比方说使用<bean:write>访问一个嵌套属性,但是用名为MyBean的基础对象而不是由<html:form>隐含的基础对象。下面是实现代码:
要用该嵌套标签完成相同事情,不得不使用<nested:root>:
如你所知(参见相应参考资料),<html:form>定义一个隐含的基础对象,它是与该表单关联的表单bean。<nested:root>允许暂时重新定义基础对象。这在<html:form>之外也是可行的。例如代码片断:
可以被替换为
4. 对应物
无。
Tiles标签库
Tiles标签库支持Tiles 插件,Tiles被用来创建布局和可重用GUI组件。第14章详细解释了Tiles,有关如何使用Tiles可参考那一章的内容。
表C-13给出了Tiles标签库中所有标签的概要。表C-13是基于Apache文档的。Apache许可证的副本可以参阅 LICENSE 。
表C-13 Tiles标签库的概要
标 签
用法/注解
insert
插入一个布局或者Tile
definition
声明一个布局或者定制布局供随后使用
put
添加一个Tiles属性至当前上下文
putList and add
putList在当前上下文中定义一个列表属性。add用来添加项目至该列表中
get
输出一个指定的JSP或者Tiles定义至响应流
getAsString
将一个指定的Tiles属性作为字面上的字符串输出至响应流
useAttribute
暴露一个Tiles属性至scriptlet或者其他定制标签
importAttribute
允许scriptlet或者其他定制标签读Tiles属性
initComponentDefinitions
允许在支柱外使用Tiles的遗产标签
公共属性
不同于其他Struts标签库,Tiles没有实际的公共属性集。然而,有许多常用的属性。这些属性被描述在表C-14中。
表C-14 Tiles标签库中的常用属性
属 性
描 述
template/component/page
这些是同义语,它们都表示包含布局信息的JSP页面
beanName/beanProperty/beanScope
这些属性用来在一个指定的JSP作用域(application、session、request、page)上,或者在Tile的ComponentContext上(而在这种情况下,使用beanScope = tile/component template——这些都是同义词)定位一个JavaBean实例。如果beanScope没有被指定,那么所有的作用域(首先是ComponentContext,然后是所有的JSP 作用域)都要被搜索,以查找命名的JavaBean实例
role
为了外围的标签能够被处理,远程用户必须具有的一个认证角色(参见在<logic:present>条目上对认证角色的讨论)。如果远程用户不具有指定的角色,包围标签则被跳过
ignore
如果被设置为true(默认是false),那么如果针对外围标签的数据(这是使用该标签的name属性来决定的;这些name属性的意义对于各个标签各不相同)没有被找到,简单地跳过到外围标签做下一步处理。ignore的默认值是false,意思指是如果该标签的数据不能发现,则抛出一个异常
flush
如果被设置为true,将导致OutputStream在该处理之前被刷新清除。这个属性是需要用来解决一些servlet容器的问题的。默认是false
关于对应物标签的附注
读者应该注意到对于Tiles是没有纯JSF或者JSTL对应物的,所以笔者对所有条目都省略了对应物一节。
针对Tiles标签库的Struts-EL标签
所有的Tiles标签都具有EL使能的版本。
注意
EL使能的标签是指那些允许使用EL表达式的标签。参看第10章的例子。
insert
这个标签插入一个页面或者Tiles布局或者控制器到外围页面中。可以使用嵌套的<tiles:put>标签定制一个布局。
1. 使用限制
必须指定要插入什么。可以使用template/component/page同义词或者definition属性或者name属性来做这件事。
2. 属性
除了通常使用的role、flush和ignore属性(参见表C-14)之外,以下属性指定插入什么东西。
· template/component/page:要插入的JSP页面的名称。
· definition:要插入的Tiles定义的名称。
· attribute:要插入的引用一个JSP页面或者Tiles定义的已定义的属性。这个属性假定你在别处已经使用<tiles:put>定义了属性。参看代码清单14-3和代码清单14-4查看如何使用这个属性。
· name:要插入的JSP页面、Tiles定义或者<tiles:put>定义的属性的名称。
· beanname/beanproperty/beanscope:这些属性用来定位一个对象(如何做参见表C-14)。被定位的对象以下面两种方式之一使用:(1)如果该对象是. . AttributeDefinition或的一个实例,那么这些属性代表要插入的一个JSP页面或者Tiles定义。说实在的,很难看到在什么时候使用它很有用。(2)否则,该对象的tostring()方法会被调用,并且其返回值被用做要插入的JSP页面、Tiles定义或者<tiles:put>定义的属性的名称。
还可以调用控制器代码来在插入被执行之前准备数据或者显示消息。要做到这些,可以指定这些属性之一:
· controllerUrl:这可以是一个表单处理器的名称或者一个URL。
· controllerClass:任何实现了. Controller接口的类。这个接口具有一个execute()方法,如代码清单14-9所述。
3. 示例
这个代码使用template/component/page来插入布局。注意前导的斜杠:
你也可以类似地插入一个Tiles定义:
关于使用<tiles:insert>的更多例子,参看第14章。
definition
这个标签声明一个布局或者它的一种定制,使它能够被重用。可以从一个<tiles:insert>标签来调用该定义从而实际地使用它。通常首先在一个共享的JSP页面声明定义,然后在利用那些定义的页面中使用<%@_ include file = "..." %>来包含那些JSP。
<tiles:definition>也允许定制一个现有的布局或者现有的定义,然后在一个或者多个JSP页面中重用那些定制版本。使用<tiles:put>和有关标签来执行定制。
注意,我在第14章没有讨论<tiles:defiinition>标签的使用,因为声明定义的一个更好的替代方式是在文件中。这能够使定义容易被跟踪和维护,并且排除了对共享JSP页面的需要。
1. 使用限制
id属性是必需的。
2. 属性
· id:指定这个定义的一个唯一的名称。
· scope:指定该定义一旦被创建所而处的的JSP作用域。默认作用域是page。设置该值为一个具有比较久的生存期的作用域(比方说session)将允许用<tiles:insert>在整个用户对话中访问那些定义。当然,如果欠考虑地使用这种方式,这种自由度将导致高维护的Web应用程序。
· template/page:持有实际的布局的JSP页面的名称。记住,那些定义仅声明一个布局。实际的布局本身是包含在一个JSP页面中的。这个页面通常包含<tiles:insert attribute = "..."/>标签来指令命名的项目的位置。关于这个问题的一个例子参看代码清单14-3。
· role:为了处理这个定义,远程用户的角色必须匹配任何一个角色。关于角色的简短讨论参见<logic:present>条目。
· extends:想要更进一步定制的父定义的名称。参见代码清单14-7查看这是如何工作的。
3. 示例
考虑这里的布局页面()代码片断:
这个布局指定了3个元素的相对位置:header、body和footer。要使用这个布局,可以在一个共享JSP页面()中像这样声明一个<tiles:definition>:
这就按照原样声明了页面,没有进行定制。然而通常在声明它的时候定制一个布局是有意义的。在前面的例子中,我们可能想要指定header和footer元素的内容。
在这段代码中,header现在指向,footer指向。所以,剩下的元素body则是不明确的。要使用该声明的定义,可以包含该共享JSP然后使用<tiles:insert>:
注意,body现在被定义来指向。
put
put定义在一个布局中的命名属性。这允许为显示定制一个布局。
1. 使用限制
put标签必须嵌套在一个<tiles:insert>或<tiles:definition>标签内部。还必须指定name属性,它引用到布局中的属性以及该属性的内容。
2. 属性
· name:put定义的属性的名称。
· value/content:代表针对一个属性的内容的URL或者字符串。value和content是同义语。
· beanName/beanProperty/beanScope:用于定位为了决定该put的值而需要询问的对象。参看表C-14获得更多细节。这些属性能被用做value或content。
· type:指示这个put的值的意义——它是一个指向JSP页面的URL(type = "page"或者type = "template"),还是一个Tiles定义(type = "definition"或者type = "instance"),还是一个字符串(type = "string")?如果没有指定,默认type ="page",除非direct = "true"。而在这种情况下,默认type = "string"。
· direct:如果设置为true,将导致值被解释为一个字面上的字符串而不是一个引用(到一个JSP页面或者Tiles定义的URL)。默认是false。
· role:为了这个put 被处理,远程用户的角色必须匹配任何一个角色。关于角色的简短讨论参见<logic:present>条目。
3. 示例
请参看<tiles:definition>条目中的例子来看看典型情况下put是怎样使用的。也可以像这样在其标签体中指定put的值:
当需要指定并不符合XML属性格式的文本的时候,这种形式是很有用的。
putList和add
putList创建一个项目列表,并且为该列表指定一个名称。一个或者多个add标签可以嵌套进一个putList中,并且被用于为该列表添加要素。
1. 使用限制
必须为putList指定name属性。
2. 属性
putList仅有一个属性name,它是该列表的名称。除了name属性之外,addtag和<tiles:put>有完全一样的属性。
3. 示例
应该理解putList和add不能轻易地被用于定制布局,就像可以用<tiles:put>进行的一样。例如,你可能期待能够定义布局的一个定制,如下面这样:
然后,在布局页面()中,可能期待这样做:
这是不行的:不能将<tiles:insert>嵌套到<logic:iterate>内部(将会抛出一个Servlet- Exception异常),必须借助于使用在项目上进行循环的scriptlet:
但这样可读性就差很多了。
get
get从Tiles的ComponentContext中读取name属性(使用<tiles:put>或<tiles:putList>放在那里的),并将其值解释为一个JSP页面或者一个Tiles定义,然后将它们的输出写入到响应流之中。
1. 使用限制
需要指定显示什么,因此name属性是必需的。
2. 属性
· name:要包含的Tiles属性的名称。
· ignore:如果由name执行的属性不能被找到,ignore = "true"将导致默认的失败。否则,抛出一个异常,这是默认行为。
· flush:这个属性具有其通常的意义(参见表C-14)。
· role:这个属性具有其通常的意义(参见表C-14)。
3. 示例
考虑此段代码:
这将导致的内容在的内容之后显示。
getAsString
这个标签类似于<tiles:get>,但是Tiles属性被解释为一个字面上的字符串。这对于显示静态文字是有用处的(例如,用在Web页面的<title>部分)。
1. 使用限制
需要指定显示什么,因此name属性是必需的。
2. 属性
· name:要显示的Tiles属性的名称,如果没有被找到,则抛出一个异常。
· flush:这个属性具有其通常的意义(参见表C-14)。
· role:这个属性具有其通常的意义(参见表C-14)。
3. 示例
考虑此段代码:
这将导致字符串""在的内容之后显示。
useAttribute
这个标签将一个Tiles属性暴露为某个给定作用域中的一个Java变量。与<tiles:import- Attribute>相对。
1. 使用限制
需要指定要暴露的Tiles属性的名称。
2. 属性
· name:要暴露的Tiles属性的名称。此属性是必需的。
· id:凭借此属性指定的名称,scriptlet或其他的标签知道该Tiles属性。如果被省略,id默认为该Tiles属性的名称。
· scope:所暴露的变量的JSP作用域(page、request、session或application)。默认值是page作用域。
· classname:所暴露的classname变量的类名。
· ignore:如果设置为true,如果该Tiles属性不能被找到,会默认失败。默认将抛出一个异常。
3. 示例
考虑此段代码:
这里,我们将Tiles属性myTilesAttr暴露为一个名为X的脚本变量。
importAttribute
importAttribute将指定的Tiles属性(用<tiles:put>或<tiles:putList>声明的)复制到指定作用域。回想一下,每个Tile都将它的属性储存在一个ComponentContext实例中,而不是直接地存放在request、session、page、application作用域中。因此需要将属性从componentcontext复制到request、session、page或application作用域中,以便非Tiles标签也能够读取该属性。importAttribute就是完成这个任务。
1. 使用限制
importAttribute需要一个从中读取属性的ComponentContext,如果ComponentContext的一个实例未找到,将抛出一个异常。这意味着必须将<tiles:importAttribute>放置在一个<tiles:insert>之后,或者一个由<tiles:insert>调用的页面之内,以确保ComponentContext已经被创建。
2. 属性
· name:指定要复制的属性的名称。如果被省略,ComponentContextare的全部属性都被复制到规定的作用域。
· scope:属性将要被复制到的JSP作用域(page、request、session或application)。默认值是page作用域。
· ignore:如果没有找到命名的属性,默认会抛出一个异常。如果设置ignore = "true"会导致importAttributeto失败。
3. 示例
考虑此段代码:
这种情况下会发生一个错误,因为<bean:write>不能够在任何作用域找到object1。要使这个例子能够工作,需要使用<tiles:importAttribute>:
initComponentDefinitions
这个标签被用于初始化Tiles子系统。回想一下,Tiles原本不是Struts的一部分,并且事实上可以将它自己单独使用。所以,这个标签只有在Struts之外使用Tiles的时候才会有用。例如,如果编写自己的servlet,这个标签就是有用的,因为它允许你自己初始化Tiles子系统,而不需要依靠Struts来为你做这件事情。说实在的,Tiles现在与Struts集成得如此紧密,以至于这个标签不再实用。
C
附录C
�. 实际上,server也可以通过()得到。——译者注
�. 这时候,Struts默认将错误保存在请求作用于_KEY常数指定的对象之中。——译者注
�. 默认情况下的关键字分别为""和""。——译者注