Struts2学习笔记(三)

一、Struts2国际化

  Struts2可以为JSP页面、Action、全局范围分别提供不同的国际化资源,这样维护系统时可以分开维护JSP页面、Action的国际化资源,从而提供更好的可维护性。Struts2国际化的步骤与Java国际化的步骤基本相似,Struts2的国际化可按如下步骤进行:

  • 让系统加载国际化资源,加载国际化资源文件有两种方式。
    • 自动加载:Action范围的国际化资源文件、包范围的国际化资源文件由系统自动加载
    • 手动加载:JSP范围的国际化资源、全局范围的国际化资源文件,分别使用标签、配置常量的方式来手动加载
  • 输出国际化,Struts2输出国际化消息同样有两种方式。
    • 在视图页面上输出国际化消息,需要使用Struts2的标签库
    • 在Action类中输出国际化消息,需要使用ActionSupport的getText()方法来完成
  如果对Java国际化有接触的话,那么对ISO语言代码和国家代码有所熟悉,通常编写的国际化资源文件的命名为:*_语言代码_国家代码
常用的语言代码:
  • 中国:zh
  • 英语:en 
  • 法语:fr
  • 德语:de
  • 日语:ja
  • 俄语:ru
常用国家&地区代码:
  • 中国:CN
  • 英国:GB
  • 法国:FR
  • 德国:DE
  • 香港:HK
  • 台湾:TW
  • 日本:JP

1.1 视图页面的国际化

  在JSP页面中指定国际化资源需要借助于Struts2的标签:<s:il8n..>

  如果把<s:il8n..>作为父标签,则其包含的所有Struts2标签都会加载<s:il8n..>内指定的国际化资源文件,使用name属性指定国际化资源文件的限定名。当然我们可以用该标签包在<html>的外面,这样整个页面的显示内容都可以使用配置好的国际化资源文件。

稍后完善——》》》

二、Struts2标签库

2.1 Struts2标签库概述

  Struts2标签库的标签不依赖于任何表现层技术,Struts2把所有的标签都定义在一个s标签库里。Struts2把所有的标签都定义在URI为“/struts-tags”空间下,但依然可以对Struts2标签进行简单的分类。Struts2可以将所有标签分为三大类:

  • UI(User Interface,用户界面)标签:主要用于生成HTML元素的标签
    • 表单标签:主要用于生成HTML页面的form元素,以及普通表单元素的标签
    • 非表单标签:主要用于生成页面上的树、Tab页等标签
  • 非UI标签:主要用于数据访问、逻辑控制等的标签
    • 流程控制标签:主要包含用于实现分支、循环等流程控制的标签
    • 数据访问标签:主要包含用于输出ValueStack中的值、完成国际化等功能的标签
  • Ajax标签:用于Ajax(Asynchronous JavaScript And XML)支持的标签
  Struts2标签库定义文件位于struts-core-*.jar文件的META-INF路径下的struts-tags.tld文件中。使用Struts2标签必须先导入标签库如下:
[html] view plain copy
  1. <%@ taglib prefix="s" uri="/struts-tags"%>  

2.2 Struts2的OGNL表达式语言

  OGNL表达式语言与JSP 2 EL的作用完全相似,而OGNL并不是真正的编程语言,只是一种数据访问语言。OGNL是Apache开源项目的子项目,其所需要的依赖包包括:ognl-*.jar和javassist-*.GA.jar。OGNL充斥在Struts2前后台数据传递与存储的方方面面,给Struts2中数据的处理带来了极大的方便。

2.2.1 OGNL基础

  OGNL(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言,除了用来设置和获取Java对象的属性之外,另外提供诸如集合的投影和过滤以及lambda表达式等。

Ognl中,常用到的两个类:

  • ognl.Ognl类:这个类主要用来解析和解释执行Ognl表达式
  • ognl.OgnlContext类:这个类为Ognl表达式提供了一个执行环境

  OgnlContext类实现了Map接口,所以允许通过put(key,obj)方法向OgnlContext环境中方式各种类型的对象。

  需要注意的是在OgnlContext中对象分为两种:

  1. 第一种是叫做root对象(根对象),在整个OgnlContext中有且最多只能有一个根对象,可以通过调用OgnlContext.setRoot(obj)设置为根对象。
  2. 第二种就是OgnlContext中的普通对象,这种个数类型不受限制。

  如果需要访问的属性属于根对象,则可以直接访问该属性;否则必须使用一个对象名作为前缀修饰该属性,并且在最前面用#修饰。其原理是这样的,如果Ognl在解析表达式的时候发现表达式开头带有"#",会去普通对象中去寻找,如果没有"#",则会默认去根对象中去寻找,由于根对象只有一个,所以只需要属性名字即可。

示例:

  dept对象就是放置到OgnlContext中的普通对象,对于这种普通对象,只能通过“#dept.name”的方式去获取属性值,需要注意的是dept指的是放置到上下文中key的值,另外在Dept类型中要提供getName方法。
Ognl中的过滤和投影:

  • 过滤与投影都是针对于数组、集合和Map而言的
  • 过滤指的是将原集合中不符合条件的对象过滤掉,然后将满足条件的对象,构建一个新的集合对象返回,Ognl过滤表达式的写法是:collection.{?|^|$ expression}
  • 投影指的是将原集合中所有对象的某个属性抽取出来,单独构成一个新的集合对象返回,基础语法为 :collection.{expression}
重要知识点:
  1. OGNL表达式需要放置到OgnlContext中才能得到正确地解析、解释和执行
  2. OgnlContext类实现了Map接口,所以可以使用put方法向里面放置元素且每个OgnlContext有且最多只能有一个根对象
  3. Ognl表达式中访问根对象的属性时,无需"#",普通对象则需要

2.2.2 Struts2中OGNL基础

  Struts2使用标准的Context来进行OGNL表达式语言求值,OGNL的顶级对象是Stack Context(有时也称为OGNL Context),Stack Context对象就是一个Map类型的实例,其根对象就是ValueStack,而ValueStack是Stack Context内的根对象,如果需要访问ValueStack里的属性,直接通过如下方式即可:${属性名}

  Struts2还提供了一些命名对象,但这些命名对象都不是根对象,只是存在于Stack Context中。所以访问这些对象时需要使用#前缀来指明:

  • parameters对象:用于访问HTTP请求参数。例如#parameters['foo]或#parameters.foo,用于返回调用HttpServletRequest的getParameter("foo")方法的返回值
  • request对象:用于访问HttpServletRequest的属性。例如#request['foo']或#request.foo,用于返回调用HttpServletRequest的getAttribute(“foo”)方法的返回值
  • session对象:用于访问HttpSession的属性。
  • application对象:用于访问ServletContext的属性。
  • attr对象:该对象将一次搜索如下对象:PageContext、HttpServletRequest、HttpSession、ServletContext中的属性
Stack Context“根”对象和普通对象的区别:
  • 访问Stack Context里的命名对象需要在对象名之前添加#前缀
  • 当访问OGNL的Stack Context里“根”对象的属性时,可以省略对象名
注:我们可以在JSP页面添加<s:debug/>标签,当打开这个JSP页面的时候,会多出来一个Debug链接,我们可以通过这个链接来访问ValueStack和Stack Context里的数据,用来辅助开发者进行调试。

2.2.3 OGNL中的集合操作

  很多时候,可能需要一个集合对象(例如List对象,或者Map对象),使用OGNL表达式可以直接创建集合对象。

  • 创建List类型集合的语法为:{e1,e2,e3...}
  • 创建Map类型集合的语法为:#{key1:value1,key2:value2...}

  对于集合,OGNL提供了两个运算符:in和not in,其中in判断某个元素是否在指定集合中;not in则用来判断某个元素是否不在指定集合中。

  OGNL还允许通过某个规则取得集合的子集,取得子集时有如下三个操作符:

  • ?:去除所有符合选择逻辑的元素
  • ^:取出符合选择逻辑的第一个元素
  • $:取出符合选择逻辑的最后一个元素
示例:person.relatives.{?#this.gender=='male'}
解析:上面的代码中,直接在集合后紧跟.{}运算符表明于取出该集合的子集,在{}内使用?表明取出所有符合选择逻辑的元素,而#this代表集合里元素。因此,上面代码的含义是:取出person的所有性别为male的relatives集合。

2.2.4 访问静态成员

  OGNL表达式还提供了一种访问静态成员(包括调用静态方法、访问静态成员变量)的方式,但Struts2默认关闭了访问静态方法,只允许通过OGNL表达式访问静态Field。为了让OGNL表达式可以访问静态方法,应该在Struts2应用中将struts.ognl.allowStaticMethodAccess设置为true,配置如下:

[html] view plain copy
  1. <!-- 设置允许通过OGNL访问静态方法 -->  
  2. <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>  

  一旦设置了上面所示常量,OGNL表达式可以通过如下语法来访问静态成员:

[html] view plain copy
  1. @className@staticField  
  2. @className@staticMethod(val...)  

2.2.5 Lambda表达式

暂不理解——》》》

2.3 控制标签

  Struts2的非UI标签包括控制标签和数据标签,主要用于完成流程控制,以及操作Struts2的ValueStack。数据标签主要结合OGNL表达式进行数据访问。控制标签包含如下9个标签:
  • if:用于控制选择输出的标签
  • elseIf/elseif:与if标签结合使用,用于控制选择输出的标签
  • else:与if标签结合使用,用于控制选择输出的标签
  • append:用于将多个集合拼接成一个新的集合
  • generator:它是一个字符串解析器,用于将一个字符串解析成一个集合
  • iterator:这是一个迭代器,用于将集合迭代输出
  • merge:用于将多个集合拼接成一个新的集合。丹玉append的拼接方式有所不同
  • sort:这个标签用于对集合进行排序
  • subset:这个标签用于截取集合的部分元素,形成一个新的子集合

2.3.1 if/elseif/else标签

示例:

[html] view plain copy
  1. <!-- 在Stack Context中定义一个age属性,其值为29 -->  
  2. <s:set name="age" value="29"/>  
  3. <!-- 如果Stack Context中的age属性大于60 -->  
  4. <s:if test="#age>60">  
  5.     老年人  
  6. </s:if>  
  7. <!-- 如果Stack Context中的age属性大于35 -->  
  8. <s:elseif test="#age>35">  
  9.     中年人  
  10. </s:elseif>  
  11. <!-- 如果Stack Context中的age属性大于15 -->  
  12. <s:elseif test="#age>15">  
  13.     青年人  
  14. </s:elseif>  
  15. <s:else>  
  16.     少年  
  17. </s:else>  
输出结果为:青年人

2.3.2 iterator标签

  iterator标签主要用于对集合进行迭代,这里的集合包含List、Set和数组,也可对Map集合进行迭代输出。使用<s:iterator.../>标签对集合进行迭代输出时,可以指定如下三个属性:
  • value:可选属性,用于指定被迭代的集合,该集合通常使用OGNL表达式指定。如果没有指定,则会默认使用ValueStack栈顶的集合
  • id:可选属性,指定集合里元素的ID
  • status:可选属性,该属性指定迭代时的IteratorStatus实例,通过该实例即可判断当前迭代元素的属性。例如是否为最后一个,以及当前迭代元素的索引等
  如果指定了status属性,每次迭代都会有一个IteratorStatus实例,该实例包含了如下几个方法:
  • int getCount():返回当前迭代了几个元素
  • int getIndex():返回当前迭代元素的索引
  • boolean isEven():返回当前被迭代元素的索引是否是偶数

  • boolean isOdd:返回当前被迭代元素的索引是否是奇数
  • boolean isFirst:返回当前被迭代元素是否是第一个元素
  • boolean isLast:返回当前被迭代元素是否是最后一个元素
示例如下:
[html] view plain copy
  1. <!-- 对指定的Map对象进行迭代输出,并指定status属性 -->  
  2. <s:iterator value="#{'疯狂Java讲义':'李刚',  
  3.     '轻量级Java EE企业应用实战':'李刚' ,  
  4.     '疯狂iOS讲义':'李刚'}"  
  5.     id="score" status="st">  
  6.     <!-- 根据当前被迭代元素的索引是否为奇数来决定是否使用背景色 -->  
  7.     <tr <s:if test="#st.odd">  
  8.         style="background-color:#bbbbbb"</s:if>>  
  9.         <!-- 输出Map对象里Entry的key -->  
  10.         <td><s:property value="key"/></td>  
  11.         <!-- 输出Map对象里Entry的value -->  
  12.         <td><s:property value="value"/></td>  
  13.     </tr>  
  14. </s:iterator>  
  前面所叙述的标签时Struts2中最常用的标签,通常Action会调用Model取出大量数据,这些数据被封装成VO(Value Object)集合(该集合通常为List或Map)传给JSP页面,而JSP页面通过这几个标签来访问这些数据。

2.3.3 append标签

  append标签用于将多个集合对象拼接起来,组成一个新的集合,通过这种拼接,从而允许通过一个<s:iterator>标签就完成对多个集合的迭代。

  通过该标签的var属性来指定新集合的名字,而该标签下可以有多个<s:param..>子标签,每个子标签指定一个集合。而新集合被放入到Stack Context中。
示例如下:

[html] view plain copy
  1. <!-- 使用append将List和Map集合拼接在一起  
  2. 新集合实际上是Map集合,其名字为newList -->  
  3. <s:append var="newList">  
  4.     <s:param  
  5.         value="#{'疯狂Java讲义':'李刚','疯狂iOS讲义':'李刚','经典Java EE企业应用实战':'李刚'}" />  
  6.     <s:param value="#{'http://www.crazyit.org','http://www.fkit.org'}" />  
  7. </s:append>  
  8. <table border="1" width="280">  
  9.     <!-- 使用iterator迭代newList集合 -->  
  10.     <s:iterator value="#newList" status="st">  
  11.         <tr <s:if test="#st.odd">  
  12.     style="background-color:#bbbbbb"</s:if>>  
  13.             <td><s:property value="key" /></td>  
  14.             <td><s:property value="value" /></td>  
  15.         </tr>  
  16.     </s:iterator>  
  17. </table>  

2.3.4 generator标签

  使用generator标签可以将指定字符串按指定分隔符分隔成多个子串,临时生成的多个子串可以使用Iterator标签来迭代输出。 注:在该标签的标签体内,整个临时生成的集合将位于ValueStack的顶端,但一旦该标签结束,该集合将被移除ValueStack。

  使用generator标签时可以指定如下几个属性:

  • count:可选属性,该属性是一个可选的属性,该属性指定生成集合中元素的总数
  • separator:必填属性,该属性指定用于解析字符串的分隔符
  • val:必填属性,该属性指定被解析的字符串
  • converter:可选属性,该属性指定要给转化器,该转换器负责将集合中的每个字符串转换成对象,通过该转换器可以将一个字符串解析成对象集合。注:该属性值必须是一个org.apache.Struts2.util.IteratorGenerator.Converter对象
  • var:可选属性,将生成的Iterator对象翻入Stack Context中。

注意:Struts2的很多标签都与该标签类似,他们都可以指定var属性,一旦指定了var属性(相当于有了句柄),则会将新生成、新设置的值放入StackContext中(必须通过#name形式访问);如果不指定var属性,则没有可以操作的句柄也就没有意义了,而且Struts处理方式是在该标签内,新生成、新设置的值有效,可以是一旦该标签结束就会被清除,也可以看做是一个局部变量吧。

2.3.5 merge标签

  merge标签与append标签作用一样都是将多个集合拼接成一个集合,使用方法也类同,只是它们采用的方法不同而已。

  • append拼接的方式是将多个集合简单的首尾相连
  • merge拼接的方式是每个集合中选取最前面的一个元素连接,然后循环持续下去,直至原集合中没有元素为止

2.3.6 subset标签

  subset标签用于取得集合的子集,该标签的底层通过org.apache.struts2.util.SubsetIteratorFilter类提供实现,该标签包含如下几个属性:

  • count:可选属性,指定子集中元素的个数,默认为取得源集合的全部元素
  • source:可选属性,指定源集合,如果不指定,则默认取得ValueStack栈顶的集合
  • start:可选属性,该属性指定子集从源集合的第几个元素开始截取。默认从第一个元素(即start的默认值为0)开始截取
  • decider:可选属性,指定有开发者自己决定是否选中该元素。该属性必须指定一个org.apache.struts2.util.SubsetIteratorFilter.Decider对象
  • var:可选属性,如果指定了该属性,则将生成的Iterator对象设置成page范围的属性
  在subset标签内时,subset标签生成的子集合放在ValueStack的栈顶,所以可以在该标签内直接迭代该标签生成的自己和。如果该标签结束后,该标签生成的子集合将被移出ValueStack栈。

下面以自定义的截取标准为例:

[java] view plain copy
  1. // 用户自定义的Decider类,实现了SubsetIteratorFilter.Decider接口  
  2. public class MyDecider implements SubsetIteratorFilter.Decider {  
  3.     // 实现Decider接口必须实现的decide()方法,  
  4.     // 该方法决定集合中的元素是否被选入子集  
  5.     public boolean decide(Object element) throws Exception {  
  6.         String str = (String) element;  
  7.         // 如果集合元素(字符串)中包含Java EE子串,即可被选入子集  
  8.         return str.indexOf("Java EE") > 0;  
  9.     }  
  10. }  
[html] view plain copy
  1. <!-- 定义一个Decider Bean -->  
  2. <s:bean var="mydecider" name="org.crazyit.app.util.MyDecider"/>  
  3. <!-- 使用自定义的Decider实例来截取目标集合,生成子集  
  4.     指定var属性,将生成的Itertor放入pageScope中 -->  
  5. <s:subset source="{'疯狂Java讲义'  
  6.     ,'轻量级Java EE企业应用实战'  
  7.     ,'经典Java EE企业应用实战'  
  8.     ,'疯狂Ajax讲义'  
  9.     ,'疯狂iOS讲义'}"   
  10.     decider="#mydecider"  
  11.     var="newList"/>  
  12. 直接输出page范围的newList属性:<br/>  
  13. ${pageScope.newList}  
  14. <table border="1" width="240">  
  15. <!-- 迭代page范围内的newList属性 -->  
  16. <s:iterator status="st" value="#attr.newList">  
  17.     <tr <s:if test="#st.odd">  
  18.         style="background-color:#bbbbbb"</s:if>>  
  19.         <td><s:property/></td>  
  20.     </tr>  
  21. </s:iterator>  
  22. </table>  

2.3.7 sort标签

  sort标签用于对栈顶的集合元素进行排序,但前提必须我们自己定义排序规则,即实现自己的Comparator,自己的Comparator需要实现java.util.Comparator接口。sort标签包含如下几个标签:
  • comparator:必填属性,该属性指定进行排序的Comparator实例
  • source:可选属性,指定被排序的集合,默认情况下对ValueStack栈顶的集合进行排序
  • var:可选属性,,如果指定了该属性,则将生成的Iterator对象设置成page范围的属性,不放入ValueStack中
示例如下:
[java] view plain copy
  1. public class MyComparator implements Comparator<Object> {  
  2.     // 决定两个元素大小的方法  
  3.     public int compare(Object element1, Object element2) {  
  4.         // 根据元素字符串长度来决定大小  
  5.         return element1.toString().length() - element2.toString().length();  
  6.     }  
  7. }  
[html] view plain copy
  1. <!-- 定义一个Comparator实例 -->  
  2. <s:bean var="mycomparator" name="org.crazyit.app.util.MyComparator"/>  
  3. <!-- 使用自定义的排序规则对目标集合进行排序 -->  
  4. <s:sort source="{'疯狂Java讲义'  
  5.     ,'轻量级Java EE企业应用实战'  
  6.     ,'经典Java EE企业应用实战'  
  7.     ,'疯狂Ajax讲义'  
  8.     ,'疯狂iOS讲义'}"   
  9.     comparator="#mycomparator"  
  10.     var="sortedList"/>  
  11. 输出page范围的sortedList属性:<br/>  
  12. ${pageScope.sortedList}  
  13. <table border="1" width="300">  
  14. <!-- 迭代page范围内的sortedList属性 -->  
  15. <s:iterator status="st" value="#attr.sortedList">   
  16.     <tr <s:if test="#st.odd">  
  17.         style="background-color:#bbbbbb"</s:if>>  
  18.         <td><s:property/></td>  
  19.     </tr>  
  20. </s:iterator>  
  21. </table>  

注:sort标签的var属性只是将排序后也只是将排序后的新集合放入pageScope中,并未放入OGNL的StackContext中。

2.4 数据标签

  数据标签主要用于提供各种数据访问的功能,包含显示一个Action里的属性,以及生成国际化输出等功能。数据标签主要包含如下几个:
  • action:该标签用于在JSP页面直接调用一个Action,通过指定executeResult参数,还可将该Action的处理结果包含到本页面中来
  • bean:该标签用于创建一个JavaBean实例。如果指定了var属性,则可以将创建的JavaBean实例放入StackContext中
  • date:用于格式化输出一个日期
  • debug:用于在页面上生成一个调试连接,当单机该链接时,可以看到当前ValueStack和StackContext中的内容
  • il8n:用于指定国际化资源文件的baseName
  • include:用于在JSP页面中包含其他的JSP或Servlet资源
  • param:用于设置一个参数,通常是用作bean标签、url标签的子标签
  • push:用于将某个值放入ValueStack的栈顶
  • set:用于设置一个新变量,并可以将新变量放入指定的范围内
  • text:用于输出国际化信息
  • url:用于生成一个URL地址
  • property:用于输出某个值,包括输出ValueStack、StackContext和ActionContext中的值

2.4.1 action标签

  使用action标签可以允许在JSP页面中直接调用Action,因为需要调用Action,所以可以指定需要被调用Action的name及namespace。如果指定了executeResult参数的属性值为true,该标签还会把Action 的处理结果(视图资源)包含到本页面来(与include功能类同)。action标签包含如下几个属性:

  • var:可选属性,一旦定义了该属性,该Action将被放入StackContext中
  • name:必填属性,该属性指定该标签调用哪个Action
  • namespace:可选属性,该属性指定该标签调用的Action所在的namespace
  • executeResult:可选属性,该属性指定是否要将Action的处理结果页面包含到本页面,默认值为false,即不包括
  • ignoreContextParams:可选参数,指定该页面中的请求参数是否需要传入调用的Action,默认值为false,即将本页面的请求参数传入被调用的Action

2.4.2 bean标签

  该标签用于创建一个JavaBean示例。创建JavaBean实例时,可以在该标签体内使用<param..>标签为该JavaBean实例传入属性。注:使用<param...>标签则需要为该JavaBean类提供相应的getter和setter方法。bean标签包含如下两个属性:
  • name:必填属性,该属性指定要实例化的JavaBean的实现类
  • var:可选属性,指定该属性,则该JavaBean实例会被放入StackContext中,并放入requestScope中
示例如下:
[html] view plain copy
  1. <!-- 使用bean标签创建一个Person类的实例,为其指定了var属性 -->  
  2. <s:bean name="org.crazyit.app.dto.Person" var="p">  
  3.     <!-- 使用param标签为Person类的实例传入参数 -->  
  4.     <s:param name="name" value="'yeeku'"/>  
  5.     <s:param name="age" value="29"/>  
  6. </s:bean>  
  7. <!-- 根据JavaBean实例指定的var属性来访问JavaBean实例 -->  
  8. Person实例的name为:<s:property value="#p.name"/><br/>  
  9. Person实例的age为:<s:property value="#p.age"/><br/>  
  10. ${requestScope.p}  

2.4.3 date标签

  date标签用于格式化输出一个日期,并且可以计算指定日期和当前时刻之间的时间差。date标签包含如下属性:
  • format:可选属性,如果指定了该属性,将根据该属性指定的格式来格式化日期
  • nice:可选属性,该属性只能为true或false,它用于指定是否输出指定日期和当前时刻之间的时间差。默认值为false,即表示不输出时间差
  • name:必填属性,指定要格式化的日期值
  • var:可选属性,指定该属性,格式化后的字符串将被放入StackContext中并放入requestScope中,但不会在页面上输出
  通常,nice属性和format属性不同时指定,如果即指定了nice=“true”,也指定了format属性,则会输出指定日期和当前时刻之间的时间差,即format属性失效。如果这两个属性都没有指定,则系统会到国际化资源文件中寻找key为struts.date.format的消息,将该消息单程格式化文本来格式化日期,如果没有找到则使用默认的DateFormat.MEDIUM格式输出。
[html] view plain copy
  1. <s:bean var="now" name="java.util.Date"/>  
  2. nice="false",且指定format="dd/MM/yyyy"<br/>  
  3. <s:date name="#now" format="dd/MM/yyyy" nice="false"/><hr/>  
  4. nice="true",且指定format="dd/MM/yyyy"<br/>  
  5. <s:date name="#now" format="dd/MM/yyyy" nice="true"/><hr/>  
  6. 指定nice="true"<br/>  
  7. <s:date name="#now" nice="true" /><hr/>  
  8. nice="false",且没有指定format属性<br/>  
  9. <s:date name="#now" nice="false"/><hr/>  
  10. nice="false",没有指定format属性,指定了var<br/>  
  11. <s:date name="#now" nice="false" var="abc"/><hr/>  
  12. ${requestScope.abc} <s:property value="#abc"/>  
  13. </body>  

2.4.4 debug标签

  debug标签主要用于辅助调试,他在页面上创建一个超链接,通过该链接可以查看到ValueStack和StackContext中的所有值信息。

2.4.5 include标签

  include标签用于将一个JSP页面,或者一个Servlet包含到本页面中。该标签包含如下属性:

  • value:必填属性,指定需要包含的JSP页面,或者Servlet
注:此标签还可以包含多个<param...>子标签,用于将多个参数值传入包含的JSP页面或者Servlet

2.4.6 param标签

  param标签主要用于为其他标签提供参数,param标签包含如下属性:

  • name:可选属性,指定需要设置参数的参数名
  • value:可选属性,指定需要设置参数的参数值
注意:如果指定name属性,则要求Component提供该属性的setter方法,系统正式根据setter方法来传入参数的;如果不提供,则外层标签必须实现UnnamedParametric接口(如TextTag)。
示例如下:
第一种用法:
[html] view plain copy
  1. <param name="color">blue</param>  
解析:该用法指定了一个名为color的参数,该参数的值为blue。
第二种用法:
[html] view plain copy
  1. <param name="color" value="blue"/>  
解析:该用法指定了一个名为color的参数,改参数的值为 blue对象的值。如果blue对象不存在,则color参数的值为null。
如果想指定color参数的值为blue字符串,则应该这样写:
[html] view plain copy
  1. <param name="color" value="'blue'"/>  

2.4.7 push标签

  push标签用于将某个值放到ValueStack的栈顶,从而可以更简单地访问该值,该标签包含如下属性:
  • value:必填属性,指定需要放到ValueStack栈顶的值
注意:因为没有var属性,也就是说没有句柄,所以只有在push标签内有效。
示例如下:
[html] view plain copy
  1. <h2>使用s:push来将某个值放入ValueStack的栈顶</h2>  
  2. <!-- 使用bean标签创建一个JavaBean实例,  
  3.     指定var属性,并将其放入Stack Context中 -->  
  4. <s:bean name="org.crazyit.app.dto.Person" var="p">  
  5.     <s:param name="name" value="'yeeku'"/>  
  6.     <s:param name="age" value="29"/>  
  7. </s:bean>  
  8. <!-- 将Stack Context中的p对象放入ValueStack栈顶-->  
  9. <s:push value="#p">  
  10.     <!-- 输出ValueStack栈顶对象的name和age属性 -->  
  11.     ValueStack栈顶对象的name属性:<s:property value="name"/><br/>  
  12.     ValueStack栈顶对象的age属性:<s:property value="age"/><br/>  
  13. </s:push>  

2.4.8 set标签

  set标签用于将某个值放入指定范围内,例如application范围、session范围等。当某个值所在的对象图非常深时,如:person.worker.wife.parent.age,每次访问比较繁琐,其可读性差,因此我们可以使用set标签,该标签相当于定义一个新变量,且将一个原有的值复制给新变量,并且可以将新变量放到指定的范围内。
set标签包含如下标签:
  • scope:可选属性,指定新变量被放置的范围,该属性可以接受application、session、request、page或action这5个值,默认值为action。(指定action范围,则该值被放入request范围中,冰杯放入到OGNL的StackContext中)
  • value:可选属性,指定将赋给变量的值。如果没有指定,则将ValueStack栈顶的值赋给新变量
  • var:可选属性,如果指定该值,则该值将会被放入ValueStack中
示例如下:
[html] view plain copy
  1. <h2>使用s:set设置一个新变量</h2>  
  2. <!-- 使用bean标签定义一个JavaBean实例 -->  
  3. <s:bean name="org.crazyit.app.dto.Person" id="p">  
  4.     <s:param name="name" value="'yeeku'"/>  
  5.     <s:param name="age" value="29"/>  
  6. </s:bean>  
  7. 将Stack Context中的p值放入默认范围(action)内。<br/>  
  8. <s:set value="#p" name="xxx"/>  
  9. Stack Context内xxx对象的name属性:<s:property value="#xxx.name"/><br/>  
  10. Stack Context内xxx对象的age属性:<s:property value="#xxx.age"/><br/>  
  11. request范围的xxx对象的name属性:${requestScope.xxx.name}<br/>  
  12. request范围的xxx对象的age属性:${requestScope.xxx.age}<hr/>  
  13. 将Stack Context中的p值放入application范围内。<br/>  
  14. <s:set value="#p" name="yyy" scope="application"/>  
  15. application范围的yyy对象的name属性:${applicationScope.yyy.name}<br/>  
  16. application范围的yyy对象的age属性:${applicationScope.yyy.age}<hr/>  
  17. 将Stack Context中的p值放入session范围内。<br/>  
  18. <s:set value="#p" name="zzz" scope="session"/>  
  19. session范围的zzz对象的name属性:${sessionScope.zzz.name}<br/>  
  20. session范围的zzz对象的age属性:${sessionScope.zzz.age}  

2.4.9 url标签

  url标签用于生成一个URL地址,可以通过为url标签指定param子元素,从而向指定URL发送请求参数。该标签包含如下几个属性:

  • action:可选属性,指定生成URL地址为哪个Action,如果Action不提供,就使用value作为URL的地址值
  • value:可选属性,指定生成URL的地址值,如果value不提供就用action属性指定的Action作为URL地址
  • anchor:可选属性,指定URL的锚点
  • encode:可选属性,指定是否需要对参数进行编码,默认是true
  • escapeAmp:可选参数,指定是否需要对&符号进行编码,默认是true
  • forceAddSchemeHostAndPort:可选参数,指定是否需要在URL对应的地址里强制添加scheme、主机和端口
  • includeContext:可选属性,指定是否需要将当前上下文包含在URL地址中
  • includeParams:可选属性,指定是否包含请求参数,该属性的属性值只能为none、get或者all,默认是get
  • method:可选属性,指定Action的方法,当使用Action来生成URL时,如果指定了该属性,则URL将链接到指定Action的特定方法
  • namespace:可选属性,该属性指定命名空间,当使用Action来生成URL时,如果指定了该属性,则URL将链接到此namespace的指定Action处
  • portletMode:可选属性,指定结果页面的portlet模式
  • scheme:可选属性,用于设置schema属性
  • var:可选属性,如果指定了该属性,将会把该链接值放入Struts2的ValueStack中
  • windowState:可选属性,指定结果页面的portlet的窗口状态
注意:action属性和value属性的作用大致相同,只是action指定的是一个Action,因此系统会自动在action指定的属性后添加.action后缀。只要指定action和value两个属性之一即可,如果两个属性都没有指定,就以当前页面作为URL的地址值。
注:portletMode和windowState都需要结合Struts2的Portlet功能才有用。
示例如下:
[html] view plain copy
  1. <h2>s:url来生成一个URL地址</h2>  
  2. 只指定value属性的形式。<br/>  
  3. <s:url value="editGadget.action"/>  
  4. <hr/>  
  5. 指定action属性,且使用param传入参数的形式。<br/>  
  6. <s:url action="showBook">  
  7.     <s:param name="author" value="'yeeku'" />  
  8. </s:url>  
  9. <hr/>  
  10. 既不指定action属性,也不指定value属性,但使用param传入参数的形式。<br/>  
  11. <s:url includeParams="get"  >  
  12.     <s:param name="id" value="%{'22'}"/>  
  13. </s:url>  
  14. <hr/>  
  15. 同时指定action属性和value属性,且使用param传入参数的形式。<br/>  
  16. <s:url action="showBook" value="xxxx">  
  17.     <s:param name="author" value="'yeeku'" />  
  18. </s:url>  

2.4.10 property标签

  property标签的作用就是输出指定值。property标签输出value属性指定的值,如果没有指定value属性,则默认输出ValueStack栈顶的值。该标签包含如下几个属性:
  • default:可选属性,如果需要输出的属性值为null,则显示default属性指定的值
  • escape:可选属性,指定是否escape HTML代码,默认值为true
  • value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出ValueStack栈顶的值

2.5 表单标签

  Struts的表单标签可分为两种:form标签本身和单个表单元素的标签。form标签的行为不同于表单元素标签,其实所有表单元素的父标签。Struts2的表单元素标签都包含了非常多的属性,担忧很多属性完全是通用的。

  所有表单标签处理类都继承了UIBean类,UIBean包含了一些通用属性,这些通用属性分成三种:
  • 模板相关属性
  • JavaScript相关属性
  • 通用属性
  除了这些属性之外,所有表单元素标签都存在一个特殊的属性:form,这个属性引用表单元素所在的表单,通过该form属性,可以谁西安表单元素和表单之间的交互。例如可通过${parameters.form.id}来取得表单元素所在表单的ID。下面详细列出这些表单标签的通用属性。
与模板相关的通用属性:
  • templateDIR:指定该表单所用的模板文件目录
  • theme:指定该表单所用的主题
  • template:指定该表单所用的模板
与JavaScript相关的通用属性如下:
  • onclick:指定鼠标在该标签生成的表单元素上单击时触发的JavaScript函数
  • ondbclic:指定鼠标在该标签生成的表单元素上双击时触发的JavaScript函数
  • onmousedown:指定鼠标在该标签生成的表单元素上按下时触发的JavaScript函数

  • onmouseup:指定鼠标在该标签生成的表单元素上松开时触发的JavaScript函数
  • onmouseover:指定鼠标在该标签生成的表单元素上悬停时触发的JavaScript函数
  • onmouseout:指定鼠标移出该标签生成的表单元素时触发的JavaScript函数
  • onfocus:指定该标签生成的表单元素得到焦点时触发的函数
  • onblur:指定该标签生成的表单元素失去焦点时触发的函数
  • onkeypress:指定单击键盘上某个键时触发的函数
  • onkeyup:指定松开键盘上某个键时触发的函数
  • onkeydown:指定按下键盘上某个键时触发的函数
  • onselect:对下拉列表项等可以选择表单元素,指定选中该元素时触发的JavaScript函数
  • onchang:对于文本框等可以接受输入的表单元素,指定当值改变时触发的JavaScript函数
注:因为HTML元素本身的限制,并不是每个HTML元素都可以触发以上的所有函数。因此,上面的属性并不是对Struts2的每个标签都有效。
  Struts2还允许为表单元素设置提示,当鼠标在这些元素上悬停时,系统将出现提示,Struts2将这种特性称为Tooltip。由于该属性特别多,其不是重点,所以不详细叙述。
  • tooltip:设置此组件的Tooltip
Struts2通用属性,用于设置表单的CSS样式:
  • cssClass :设置该表单元素的class属性
  • cssStyle:设置该表单元素的style属性,使用内联的CSS样式
  • title:设置表单元素的title属性
  • disabled:设置表单元素的disaled属性
  • lable:设置表单元素的label属性
  • labelPosition:设置表单元素的lable所在位置,可接受的值为top(上面)和left(左面),默认是在左边
  • requiredposition:定义必填标记(默认以“*”作为必填标记)位于label元素的位置,可接受的值为left(左面)和right(右边),默认为右边
  • name:定义表单元素的name属性,该属性值用于与Action属性形成对应
  • required:定义是否在表单元素的label上增加必填标记(默认以“*”作为必填标记),这职位true是增加必填标记,否则不增加
  • tabIndex:设置表单元素的tabindex属性
  • value:设置表单元素的value属性

2.5.1 表单标签的name和value属性

  对于表单标签而言,name和value属性之间存在一个特殊的关系:因为每个表单元素会被映射成Action属性,所以如果某个表单对应的Action已经被实例化(该表单被提交过)、且其属性有值时,则该Acting对应表单里的表单元素会显示出该属性的值,这个值将作为表单标签的value。

  name属性设置表单元素的民资,表单元素的名字实际上封装着一个请求参数,而请求参数是被封装到Action属性的。因此,可以将该name属性指定为你希望绑定值的表达式。
  也就是说,表单标签的name属性值可使用表达式,有时候还希望表单元素里可以显示出对应Action的属性值,因为name和value属性存在这种特殊关系,所以使用Struts2标签库时,无须指定value属性,因为Struts2标签会自动处理这些。代码如下:
[html] view plain copy
  1. <!-- 将下面文本框的值绑定到Action的person属性的firstName属性 -->  
  2. <s:textfield name="person.firstName"/>  
  虽然上面的文本框没有指定value属性,但Struts2一样会在该文本框中输出对应Action里的person属性的firstName属性值(如果该Action已经被实例化,且其person属性有对应的值)。Struts2提供了很多表单标签,大部分表单标签和HTML表单元素之间有一一对应的关系。

2.5.2 checkboxlist标签

  checkboxlist标签可以一次创建多个复选框,用于同时生成多个<input type="checkbox"...>的HTML标签。它根据list属性指定的集合生成多个复选框,因此,使用该标签指定一个list属性。除此之外,其他属性大部分是通过属性。除此之外,checkboxlist表单还有如下两个常用属性:
  • listKey:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的value。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为复选框的value。
  • listValue:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的标签。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为复选框的标签。

示例如下:

[java] view plain copy
  1. public class Book {  
  2.     private String name;  
  3.     private String author;  
  4.     // 无参数的构造器  
  5.     public Book() {  
  6.     }  
  7.     // 初始化全部成员变量的构造器  
  8.     public Book(String name, String author) {  
  9.         this.name = name;  
  10.         this.author = author;  
  11.     }  
  12.     //省略name和author的setter和getter方法  
  13. }  
[java] view plain copy
  1. public class BookService {  
  2.     public Book[] getBooks() {  
  3.         return new Book[] { new Book("疯狂Java讲义""李刚"), new Book("轻量级Java EE企业应用实战""李刚"), new Book("疯狂iOS讲义""李刚"),  
  4.                 new Book("疯狂Ajax讲义""李刚") };  
  5.     }  
  6. }  
[html] view plain copy
  1. <h3>使用s:checkboxlist生成多个复选框</h3>  
  2. <s:form>  
  3. <!-- 使用简单集合来生成多个复选框 -->  
  4. <s:checkboxlist name="a" label="请选择您喜欢的图书"   
  5.     labelposition="top" list="{'轻量级Java EE企业应用实战'  
  6.     , '疯狂iOS讲义'  
  7.     , '疯狂Java讲义'}"/>  
  8. <!-- 使用简单Map对象来生成多个复选框  
  9.     使用Map对象的key(书名)作为复选框的value,  
  10.     使用Map对象的value(出版时间)作为复选框的标签-->  
  11. <s:checkboxlist name="b" label="请选择您想选择出版日期"   
  12.     labelposition="top" list="#{'疯狂Java讲义':'2008年9月'  
  13.     ,'轻量级Java EE企业应用实战':'2008月12月'  
  14.     ,'疯狂iOS讲义':'2014年1月'}"  
  15.     listKey="key"  
  16.     listValue="value"/>  
  17. <!-- 创建一个JavaBean对象,并将其放入Stack Context中 -->  
  18. <s:bean name="org.crazyit.app.service.BookService" var="bs"/>  
  19. <!-- 使用集合里放多个JavaBean实例来生成多个复选框  
  20.     使用集合元素里name属性作为复选框的标签  
  21.     使用集合元素里author属性作为复选框的value-->  
  22. <s:checkboxlist name="b" label="请选择您喜欢的图书"   
  23.     labelposition="top"  
  24.     list="#bs.books"  
  25.     listKey="author"  
  26.     listValue="name"/>  
  27. </s:form>  

效果图:


2.5.3 radio标签

  radio标签的用法与checkboxlist用法几乎完全相同,一样可以指定label、list、listKey和listValue等属性,与checkboxlist唯一不同的是,checkboxlist生成多个复选框,而radio生成多个单选按钮
示例如下:

[html] view plain copy
  1. <h3>使用s:radio生成多个单选框</h3>  
  2. <s:form>  
  3. <!-- 使用简单集合来生成多个单选框 -->  
  4. <s:radio name="a" label="请选择您喜欢的图书" labelposition="top"  
  5.     list="{'疯狂Java讲义','轻量级Java EE企业应用实战',  
  6.         '疯狂iOS讲义'}"/>  
  7. <!-- 使用简单Map对象来生成多个单选框 -->  
  8. <s:radio name="b" label="请选择您想选择出版日期" labelposition="top"  
  9.     list="#{'疯狂Java讲义':'2008年9月'  
  10.     ,'轻量级Java EE企业应用实战':'2008月12月'  
  11.     ,'疯狂iOS讲义':'2014年1月'}"  
  12.     listKey="key"  
  13.     listValue="value"/>  
  14. <!-- 创建一个JavaBean实例 -->  
  15. <s:bean name="org.crazyit.app.service.BookService" id="bs"/>  
  16. <!-- 使用集合里放多个JavaBean实例来生成多个单选框 -->  
  17. <s:radio name="c" label="请选择您喜欢的图书" labelposition="top"  
  18.     list="#bs.books"  
  19.     listKey="author"  
  20.     listValue="name"/>  
  21. </s:form>  

效果图:


2.5.4 select标签

  select标签用于生成一个下拉列表,使用该标签必须指定list属性,系统会给list属性指定的结合来生成下拉列表框。这个list属性指定的集合,既可以是普通集合,也可以是Map对象,还可以是元素对象的集合。除此之外,select表单还有如下几个常用属性:
  • listKey:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的value。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为复选框的value。
  • listValue:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的标签。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为复选框的标签。
  • multiple:设置该列表框是否允许多选
示例如下:
[html] view plain copy
  1. <h3>使用s:select生成下拉选择框</h3>  
  2. <s:form>  
  3. <!-- 使用简单集合来生成下拉选择框 -->  
  4. <s:select name="a" label="请选择您喜欢的图书" labelposition="top"   
  5.     multiple="true" list="{'疯狂Java讲义','轻量级Java EE企业应用实战',  
  6.     'JavaScript: The Definitive Guide'}"/>  
  7. <!-- 使用简单Map对象来生成下拉选择框 -->  
  8. <s:select name="b" label="请选择您想选择出版日期" labelposition="top"   
  9.     list="#{'疯狂Java讲义':'2008年9月',  
  10.     '轻量级Java EE企业应用实战':'2008月12月',   
  11.     '疯狂iOS讲义':'2014年1月'}"  
  12.     listKey="key"  
  13.     listValue="value"/>  
  14. <!-- 创建一个JavaBean实例 -->  
  15. <s:bean name="org.crazyit.app.service.BookService" id="bs"/>  
  16. <!-- 使用集合里放多个JavaBean实例来生成下拉选择框 -->  
  17. <s:select name="c" label="请选择您喜欢的图书" labelposition="top"  
  18.     multiple="true"  
  19.     list="#bs.books"  
  20.     listKey="author"  
  21.     listValue="name"/>  
  22. </s:form>  

效果图:


2.5.5 optgroup标签

  optgroup标签用于生成一个下拉列表框的选项组,因此该标签必须放在<s:select...>标签中使用。一个下拉列表框中可以包含多个选项组,因此可以在一个<s:select...>标签中使用多个<s:optgroup...>标签。该标签一样需要指定list、listKey和listValue等属性,除此之外,使用该标签也可以指定label属性,但这个label属性不是下拉列表框的label,而是该选项组的组名。

示例如下:
[html] view plain copy
  1. <h3>使用s:optgroup生成下拉选择框的选项组</h3>  
  2. <s:form>  
  3. <!-- 直接使用Map为列表框生成选项 -->  
  4. <s:select label="选择您喜欢的图书" name="book" size="7"  
  5.     list="#{'疯狂Java讲义':'李刚'  
  6.         ,'轻量级Java EE企业应用实战':'李刚'  
  7.         ,'疯狂iOS讲义':'李刚'}"  
  8.     listKey="value"  
  9.     listValue="key">  
  10.     <!-- 使用Map对象来生成选择框的选项组 -->  
  11.     <s:optgroup label="Rod Johnson"  
  12.         list="#{'Expert One-on-One J2EE Design and Development':'Johnson'}"  
  13.         listKey="value"  
  14.         listValue="key"/>  
  15.     <s:optgroup label="David Flanagan"  
  16.         list="#{'JavaScript: The Definitive Guide':'David'}"  
  17.         listKey="value"  
  18.         listValue="key"/>  
  19. </s:select>  
  20. </s:form>  

效果图:


2.5.6 head标签(暂不理解)

  该标签主要用于生成HTML页面的<head...>部分。因为有些主题需要包含特定的CSS和JavaScript代码,而该标签 用于生成对这些CSS和JavaScript代码的引用。

  例如,如果需要在页面中使用Ajax组件,则使用一个带theme=“ajax”属性的head标签,就可以将标准的Ajax的头信息包含在页面中。使用Ajax主题时,可以通过设置head标签的debug参数为true,从而打开调试标志。

注:一般使用Struts的UI标签、JavaScript客户端校验等需要JavaScript库和CSS支持功能时,都应该先使用head标签。

2.5.7 updownselect标签

  该标签非常类似于select标签,区别是该标签生成的列表框可以上下移动选项。因此使用该标签时,一样可以指定list、listKey和listValue等属性,除此之外,其还支持如下几个属性:

  • allowMoveUp:是否显示“上移”按钮,默认是true
  • allowMoveDown:是否显示“下移”按钮,默认是true
  • allowSelectAll:是否显示“全选”按钮,默认是true
  • moveUpLabel:设置“上移”按钮上的文本,默认是∧按钮
  • moveDownLabel:设置“下移”按钮上的文本,默认是∨按钮
  • selectAllLabel:设置“全选”按钮上的文本,默认是*符号
示例如下:
[html] view plain copy
  1. <h3>使用s:updownselect生成可上下移动选项的下拉选择框</h3>  
  2. <s:form>  
  3. <!-- 使用简单集合来生成可上下移动选项的下拉选择框 -->  
  4. <s:updownselect name="a" label="请选择您喜欢的图书"  
  5.     labelposition="top"  
  6.     moveUpLabel="向上移动"  
  7.     list="{'疯狂Java讲义'   
  8.     , '轻量级Java EE企业应用实战'  
  9.     , '疯狂iOS讲义'}"/>  
  10. <!-- 使用简单Map对象来生成可上下移动选项的下拉选择框   
  11.      且使用emptyOption="true"增加一个空选项-->  
  12. <s:updownselect name="b" label="请选择您想选择出版日期"  
  13.     labelposition="top"  
  14.     moveDownLabel="向下移动"  
  15.     list="#{'疯狂Java讲义':'2008年9月'  
  16.     ,'轻量级Java EE企业应用实战':'2008月12月'  
  17.     ,'疯狂iOS讲义':'2014年1月'}"  
  18.     listKey="key"  
  19.     emptyOption="true"  
  20.     listValue="value"/>  
  21. <s:bean name="org.crazyit.app.service.BookService" id="bs"/>  
  22. <!-- 使用集合里放多个JavaBean实例来可上下移动选项的生成下拉选择框 -->  
  23. <s:updownselect name="c" label="请选择您喜欢的图书的作者"  
  24.     labelposition="top" selectAllLabel="全部选择" multiple="true"  
  25.     list="#bs.books"  
  26.     listKey="author"  
  27.     listValue="name"/>  
  28. </s:form>  
效果图:

2.5.8 doubleselect标签

  该标签会生成一个级联李表框(会生成两个下拉列表框),这两个列表框是关联的,下面是其常用的属性:
  • list:指定用于输出第一个下拉列表框中选项的集合
  • listKey:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的value。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为第一个下拉列表框的value。
  • listValue:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的标签。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为作为第一个下拉列表框的标签。
  • doubleList:用于输出第二个下拉列表框中选项的集合
  • doubleListKey:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的value。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为第二个下拉列表框的value。
  • doubleListValue:该属性指定集合元素中的某个属性(例如集合元素为Person实例,指定Person实例的name属性)作为复选框的标签。如果集合是Map,则可以使用key或value值指定Map对象的key或value作为作为第二个下拉列表框的标签。
  • doubleName:指定第二个下拉列表框的name属性
示例如下:
[html] view plain copy
  1. <h3>使用s:doubleselect生成级联下拉列表框</h3>  
  2. <s:form action="x">  
  3.     <s:doubleselect  
  4.         label="请选择您喜欢的图书"  
  5.         name="author" list="{'李刚', 'David'}"  
  6.         doubleList="top == '李刚' ? {'轻量级Java EE企业应用实战',  
  7.         '疯狂iOS讲义','疯狂Java讲义'}:  
  8.         {'JavaScript: The Definitive Guide'}"   
  9.         doubleName="book"/>    
  10. </s:form>  

效果图:


2.5.9 optiontransferselect标签

  optiontransferselect会生成两个列表选择框,并生成系列的按钮用于控制各选项在两个下拉列表之间的移动、升降等。当提交该表单时,两个列表选择框对应的请求参数都会被提交。因为该标签会生成两个列表框,因此需要分别制定两个列表框中的集合、lable等属性,下面是该标签常用的属性:
  • addAllToLeftLable:设置全部移动到左边按钮上的文本
  • addAllToRightLable:设置全部移动到右边按钮上的文本
  • addToLeftLable:设置向左移动按钮上的文本
  • addToRightLable:设置向右移动按钮上的文本
  • allowAddAllToLeft:设置是否出现全部移动到左边的按钮
  • allowAddAllToRight:设置是否出现全部移动到右边的按钮
  • allowAddToLeft:设置是否出现移动到左边的按钮
  • allowAddToRight:设置是否出现移动到右边的按钮
  • leftTitle:设置左边列表框的标题
  • rightTitle:设置右边列表框的标题
  • allowSelectAll:设置是否出现全部选择按钮
  • selectAllLable:设置全部选择按钮上的文本
  • doubleList:必填属性,设置用于创建第二个下拉框的集合
  • doubleListKey:设置第二个下拉选择框的选项value的属性
  • doubleListValue:设置创建第二个下拉选择框的选项label的属性
  • doubleName:必填属性,设置第二个下拉选择框的name属性
  • doubleValue:设置第二个下拉选择框的value属性
  • doubleMultiple:设置第二个下拉选择框是否允许多选
  • list:设置用于创建第一个下拉选择框的选项value的属性
  • listKey:设置创建第一个下拉选择框的选项value的属性
  • listValue:设置创建第一个下拉选择框的选项label的属性
  • name:设置第一个下拉选择框的name属性
  • value:设置第一个选择框的value属性
  • multiple:设置第一个下拉选择框是否允许多选

示例如下:

[html] view plain copy
  1. <h3>使用s:optiontransferselect来生成可移动列表项的下拉列表框</h3>  
  2. <s:form>  
  3. <!-- 使用简单集合对象来生成可移动的下拉列表框 -->  
  4.  <s:optiontransferselect   
  5.     label="请选择你喜欢的图书"  
  6.     name="cnbook"   
  7.     leftTitle="中文图书:"  
  8.     rightTitle="外文图书"  
  9.     list="{'疯狂Java讲义' ,'疯狂iOS讲义',  
  10.         '轻量级Java EE企业应用实战','经典Java EE企业应用实战'}"   
  11.     multiple="true"  
  12.     addToLeftLabel="向左移动"  
  13.     selectAllLabel="全部选择"  
  14.     addAllToRightLabel="全部右移"  
  15.     headerKey="cnKey"  
  16.     headerValue="--- 选择中文图书 ---"  
  17.     emptyOption="true"  
  18.     doubleList="{'Expert One-on-One J2EE Design and Development',  
  19.         'JavaScript: The Definitive Guide'}"   
  20.     doubleName="enBook"  
  21.     doubleHeaderKey="enKey"  
  22.     doubleHeaderValue="--- 选择外文图书 ---"   
  23.     doubleEmptyOption="true"  
  24.     doubleMultiple="true"  
  25. />  
  26. </s:form>  

效果图:


2.5.10 token标签

  这是一个防止重复提交表单的标签,token标签能组织重复提交表单的问题(避免刷新页面导致的重复提交)。如果需要该标签起作用,则应该在Struts2的配置文件中启用TokenInterceptor拦截器或TokenSessionStoreInterceptor拦截器。这个标签无需在页面上生成任何输出,也无需开发者手动控制,因此使用该标签无须指定任何属性。

原理:token标签的实现原理是在表单中增加一个隐藏域,每次加载该页面时,该隐藏域的值都不相同。而TokenInterceptor拦截器则拦截所有用户请求,如果两次请求时该token对隐藏域的值相同(前一次提交时token隐藏域的值保存在session里),则阻止表单提交。
注意:在默认情况下,token标签生成的隐藏域的name为struts.token。因此,不要在表单中另外定义一个名为struts.token的表单域。

示例如下:

[java] view plain copy
  1. <h3>使用s:token防止重复提交</h3>  
  2. <s:form action="pro">  
  3.     <!-- 普通表单域 -->  
  4.     <s:textfield name="book" label="书名"/>  
  5.     <!-- 用于防刷新的token -->  
  6.     <s:token/>  
  7.     <s:submit value="提交"/>  
  8. </s:form>  
Action配置:
[html] view plain copy
  1. <!-- 定义名为pro的Action,其实现类为ProAction -->  
  2. <action name="pro" class="org.crazyit.app.action.ProAction">  
  3.     <!-- 使用系统默认的拦截器栈 -->  
  4.     <interceptor-ref name="defaultStack"/>  
  5.     <!-- 使用防刷新的token拦截器 -->  
  6.     <interceptor-ref name="token"/>  
  7.     <!-- 定义重复提交转向的视图,该逻辑视图名必须是invalid.token -->  
  8.     <result name="invalid.token">/WEB-INF/content/refresh.jsp</result>  
  9.     <!-- 如果处理结果返回success,对应/show.jsp视图资源 -->  
  10.     <result>/WEB-INF/content/show.jsp</result>  
  11. </action>  
正如上面的步骤:
  1. 页面中添加token标签
  2. 配置Action时启动token拦截器,并为invalid.token逻辑视图指定物理资源
这样该Action就可以实现防刷新功能,如果用户通过刷新向pro.action提交两次请求,将看到系统自动转入refresh.jsp页面。

注意:如果表单页面没有使用<s:token/>标签,则千万不要使用token拦截器,否则它将导致无法提交表单。
效果图:

2.6 非表单标签

  非表单标签主要用于在页面中生成一些非表单的可视化元素,例如Tab页面、输出HTML页面的树形结构等。当然,非表单标签也包含在页面中显示Action里封装的信息。非表单标签主要有如下几个:

  • actionerror:如果Action实例的getActionErrors()方法返回不为null,则该标签负责输出该方法反悔的系列错误
  • actionmessage:如果Action实例的getActionMessages()方法返回不为null,该标签负责输出该方法返回的系列信息
  • component:使用此标签可以生成一个自定义组件
  • fielderror:如果Action实例存在表单域的类型转换错误、校验错误,该标签则负责输出这些错误提示
参考资料:

《轻量级JavaEE企业应用实战 第四版》

OGNL表达式语言详解

最后修改时间:2017年3月29日16:13:35

********************************************************************************结束语********************************************************************************************

  我在写这篇博客的时候也是一名初学者,有任何疑问或问题请留言,或发邮件也可以,邮箱为:fanxiaobin.fxb@qq.com,我会尽早的进行更正及更改。
在我写过的博客中有两篇博客是对资源的整理,可能对大家都有帮助,大家有兴趣的话可以看看!!
下载资料整理——目录:http://blog.csdn.net/fanxiaobin577328725/article/details/51894331
  这篇博客里面是我关于我见到的感觉不错的好资源的整理,里面包含了书籍及源代码以及个人搜索的一些资源,如果有兴趣的可以看看,我会一直对其进行更新和添加。
优秀的文章&优秀的学习网站之收集手册http://blog.csdn.net/fanxiaobin577328725/article/details/52753638
  这篇博客里面是我对于我读过的,并且感觉有意义的文章的收集整理,纯粹的个人爱好,大家感觉有兴趣的可以阅读一下,我也会时常的对其进行更新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值