与struts1标签库进行比较,struts2的标签库有一个巨大的改进之处就是struts2标签库不依赖于任何表现层技术。就是说struts2的大部分标签可以在jsp页面中使用,也可以在Velocity和FreeMarker等模板技术中使用。
Struts2的标签都定义在s标签库中,URI为/struts-tags的空间下。简单的对struts2的标签进行分类:
UI标签,用于HTML元素的标签。
非UI标签,主要用于数据访问,逻辑控制等的标签。
Ajax标签,用于Ajax支持的标签。
首先将struts-tags.tld文件拷贝到web应用项目中,例如我们拷贝到了/WEB-INF/tag/struts-tags.tld下。/,表示当前web应用的根目录。
然后,打开web.xml,去配置tag标签。<taglib-uri>...</taglib-uri>之间配置标签库的uri,<taglib-location>...</taglib-location>之间配置具体的struts-tags.tld的存放位置。标签库的配置必须放置在<taglib>...</taglib>之间。
<taglib>
<taglib-uri>
/struts-tags
</taglib-uri>
<taglib-location>
/WEB-INF/tag/struts-tags.tld
</taglib-location>
</taglib>
如果Web应用使用Servlet 2.4以上的规范,则无需在web.xml文件中配置标签库定义,因为Servlet 2.4规范会自动加载标签库定义文件。
使用struts2标签必须先导入标签库,在JSP页面中使用如下代码来导入struts2标签库:
<%@taglib prefix="s" uri="/struts-tags"%>
其中URI就是struts2标签库的URI,而prefix属性值是该标签库的前缀。例如:
<s:abc .../>
*****************************************
OGNL表达式语言
OGNL是一个对象,属性的查询语言。在OGNL中有一个类型为Map的Context(称为上下文),在这个上下文中有一个根元素(root),对根元素的属性的访问可以直接使用属性名字,但是对于其他非根元素中的属性的访问必须加上特殊符号#。
OGNL context Map包括:
application,session,value stack(root),require,parameters,attr
在Struts2中上下文为ActionContext,根元素位Value Stack(值堆栈,值堆栈代表了一族对象而不是一个对象,其中Action类的实例也属于值堆栈的一个)。因为Action实例被放在Value Stack中,而Value Stack又是根元素(root)中的一个,所以对Action中的属性的访问可以不使用标记#,而对其他的访问都必须使用#标记。例如:#foo.blah,表示取得Context中名字为foo对象的blah属性。相当于执行foo.getBlah()方法。
parameters对象,用于访问http请求参数,例如#parameters[‘foo‘]或#parameters.foo用于范围调用HttpservletRequest的getParameter("foo")方法的返回值。
request对象,用于访问httpServletRequest属性。例如:#request[‘foo‘]或#request.foo,用于返回调用HttpServletRequest的getAttribute("foo")方法的返回值。
session对象,用于访问HttpSession的属性。例如:#session[‘foo‘]或#session.foo
application对象,用于访问ServletContext的属性。例如:#application[‘foo‘]或#application.foo
attr对象,用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止。
根据上面的,jsp页面中的表单的某个元素的name属性可以直接为Action中某个VO类实例名称.属性名,这样可以直接将元素的值存储到VO类的属性中。如:
<input name="corpInfoVO.standbyEmail" class="on_tx5" type="text" maxlength="50" id="standbyemail"/>
OGNL支持所有常量类型:
字符串常量:以单引号或双引号括起来的字符串。注意,如果是单个字符的字符串常量,必须使用双引号。
字符常量:以单引号(‘‘)括起来的字符。
数值常量:除了java中的int,long,float和double外,OGNL还让你使用"b"或"B"后缀指定BigDecimal常量,用"h","H"后缀指定BigInteger常量。
布尔常量:true或false。
null常量
OGNL中的集合:
List集合,格式类似于:{e1,e2,e3...}该集合包含了三个元素:e1,e2,e3。如果需要更多的元素,则多个元素之间用英文逗号隔开。
Map集合,格式类似于:#{key1:value1,key2:value2,...},直接生成一个Map集合,该Map对象中每个key-value对象之间以英文冒号隔开,多项之间以英文逗号隔开。
例如:
<s:if test="‘foo‘ in {‘foo‘,‘bar‘}">
...
</s:if>
花括号{},用于创建集合,元素之间用逗号分隔。
in和not in,用于判断一个值是否在集合中。
访问javaBean的属性
假如有一个employee对象作为OGNL上下文的根对象,那么对于下面的表达式:
name,对应的java代码是employee.getName();
address.country,对应的java代码是employee.getAddress().getCountry();
%,用于在标志的属性为字符串类型时,计算OGNL表达式的值。%{#foo[‘foo1‘]}。如%{getText(‘key‘)}可以取出国际化信息
$,有两个主要的用途
用于在国际化资源文件中,引用OGNL表达式。例如在struts2的配置文件中:
<result type="redirect">ListPhoto.action?albumld=${albumld}</result>
***************************************
struts2的非UI标签包括控制标签和数据标签,主要用于完成流程控制。
1 if、elseif、else标签
这三个标签都是用于进行分支控制。3个标签组合使用,只有<s:if.../>标签可以单独使用,后面的<s:elseif../>和<s:else.../>都是不可单独使用,必须和<s:if.../>标签结合使用。它们可以取代JSP脚本的if语句,if标签和else标签可以接受一个test属性,该属性确定执行判断的boolean表达式。
例如:
<s:set name="age" value="29"/>
<s:if test="表达式">
标签体
</s:if>
<s:elseif test="表达式">
标签体
</s:elseif>
.....
<s:else>
标签体
</s:else>
s-if.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<body>
<!--在Stack Context中定义一个age属性,其值为29-->
<s:set name="age" value="29"/>
<!--如果Stack Context中的age的属性大于60-->
<s:if test="#age>60">
老年人
</s:if>
<s:elseif test="#age>35">
中年人
</s:elseif>
<s:elseif test="#age>15">
青年人
</s:elseif>
<s:else>
少年
</s:else>
对于<if.../>标签,<elseif.../>标签必须指定一个test属性,该test属性就是进行条件判断的。
</body>
</html>
test="表达式"也可以为某对象的属性,如 test="#user.age>35"。
2 iterator标签
iterator标签主要用于对集合进行迭代,这里的集合包括List,Set和数组,也可对Map集合进行迭代输出。使用</s:iterator.../>标签进行迭代输出时,可以指定三个属性:
value,这是一个可选的属性,value属性指定被迭代的集合,被迭代的集合通常都是使用OGNL表达式指定。如果没有指定value属性,则使用ValueStack栈顶的集合。
id,是一个可选属性,该属性的值代表了集合里元素。取值为字符串。
status,这是一个可选属性,该属性指定迭代时IteratorStatus实例。通过该实例可以判断当前迭代元素的属性。例如是否是最后一个,以及当前迭代元素的索引等。该实例包含了如下的几个属性:
count(),返回当前已经迭代了几个元素。
index(),返回当前迭代元素的索引。
even(),返回当前被迭代元素是否是偶数。
first(),返回当前被迭代元素是否是第一个元素。
last(),返回当前被迭代元素是否是最后一个元素。
odd(),返回当前被迭代元素的索引是否是奇数。
例如:
<s:iterator value="{‘struts2权威指南‘,‘轻量级j2ee‘,‘tested‘}" id="ne" status="st">
//对当前迭代元素的属性进行判断。判断其索引是否为奇数
<s:if test="#st.odd">
<tr>
<td>
//ne代表集合中的元素
<s:property value="ne" />
</td>
</tr>
</s:if>
</s:iterator>
<%
List list = new ArrayList();
list.add("Max");
list.add("Scott");
list.add("Jeffry");
list.add("Joe");
list.add("Kelvin");
request.setAttribute("names", list);
%>
<ol>
<s:iterator value="#request.names" id="ne" status="stuts">
<!--根据当前索引进行判断-->
<s:if test="#stuts.index > 2">
<li>White <s:property value="ne"/></li>
</s:if>
<s:else>
<li style="background-color:gray"><s:property value="ne"/></li>
</s:else>
</s:iterator>
</ol>
迭代Map:
tradeMap.keySet()得到Map的key的set集合,t就是该set集合中的值,那么${t}代表Map的key,trademap.get(#t)就得到该key(#t)对应value。
<s:iterator id="t" value="tradeMap.keySet()" status="st">
<option value="${t}"><s:property value="tradeMap.get(#t)"/> </option>
</s:iterator>
</select>
当Action的某个属性为List对象,如:
private List<dgzzUserVo> listdguser;
因为Action的属性时放置在根元素(Value Stack)下,所以对Action属性的访问可以不加#号。又该List中的每个元素时一个dgzzUserVO,而dgzzUserVO是不在根元素下的,所以对它的访问需要加上#,如下所示:
<s:iterator value="listdguser" id="dguserVO" status="stuts">
<tr>
<td><s:property value="#dguserVO.userID"/></td>
<td><s:property value="#dguserVO.userName"/></td>
<td><s:property value="#dguserVO.email"/></td>
<td><s:property value="#dguserVO.relationMan"/></td>
<td><s:property value="#dguserVO.phone"/></td>
</tr>
又因为List<dgzzUserVo>是泛型,所以也可以采用如下方式:
<s:iterator value="listdguser" id="dguserVO" status="stuts">
<tr>
<td><s:property value="userID"/></td>
<td><s:property value="userName"/></td>
<td><s:property value="email"/></td>
<td><s:property value="relationMan"/></td>
<td><s:property value="phone"/></td>
</tr>
3append标签
append标签用于将多个集合对象拼接起来,组合成一个新的集合。从而允许通过一个<s:iterator.../>标签完成对多个集合的迭代。使用<s:append.../>标签时需要指定一个var属性,也可以使用id属性但推荐使用var,该属性确认拼接生成的新集合的名字。另外<s:append.../>标签可以接受多个<s:param.../>子标签,每个子标签指定一个集合,<s:append../>负责将<s:param.../>标签指定的多个集合拼接成一个集合。例如:
<table>
<s:append id="newList">
<s:param value="{‘struts1‘,‘struts2‘}"/>
<s:param value="{‘http://www.crazyit.net.cn‘,‘http://www.crazyit.org‘}"/>
</s:append>
<s:iterator value="#newList" status="st" id="ele">
<tr>
<td><s:property value="#st.count"/></td>
<td><s:property value="ele"/></td>
</tr>
</s:iterator>
</table>
下例中将Action中的三个List对象连接成一个List,并将这个List迭代输出:
<s:append id="myAppendIterator">
<s:param value="myList1" />
<s:param value="myList2" />
<s:param value="myList3" />
</s:append>
<s:iterator value="#myAppendIterator">
<s:property />
</s:iterator>
4 generator标签
使用generator标签可以将制定字符串按指定分隔符分隔成多个子串,临时生成的多个子串可以使用Iterator标签来迭代输出。可以说是:generator将一个字符串转化成一个List集合,在该标签的标签体内,整个临时生成的集合将位于ValurStact的顶端,一旦该标签结束,该集合将被移除ValueStack。
使用generator标签时可以指定如下属性:
count,该属性是一个可选的的属性,该属性指定生成集合中的元素总数。
separator,必填属性,该属性指定用于解析字符串的分隔符。
val,这是一个必填属性,该属性指定用于解析字符串的分隔符。
var,这是一个可选属性,如果指定了该属性,该属性将生成的Iterator对象放入Stack Context中。也可替换成id。
例如:
<s:generator var="newlist1" val="‘struts2权威指南,轻量级j2ee,tested‘" separator=","></s:generator>
<table>
<s:iterator value="#newlist1" var="ee">
<tr><td><s:property value="ee"/></td></tr>
</s:iterator>
</table>
下面的例子中sss是Action中的一个属性。注意var的取值不能为new,因为new是关键字
<s:generator separator="," val="sss" var="new2"></s:generator>
<table>
<s:iterator value="#new2" var="ee">
<tr><td><s:property value="ee"/></td></tr>
</s:iterator>
</table>
5 merge标签
merge标签的用法看起来非常像append标签,也是用于将多个集合拼接成一个集合,但它采用的拼接方式与append的拼接方式不同,是交叉着拼接。
6 subset标签
subset标签用于取得集合的子集。使用subset标签时可以指定如下几个属性:
count,这是一个可选属性,该属性指定子集中元素的个数。如果指定该属性,则默认取得原集合中的全部元素。
source,这是一个可选属性,该属性用于指定源集合。如果不指定该属性,则默认取得ValueStack栈顶的集合。
start,这是一个可选属性,该属性指定子集从源集合的第几个元素开始截取。默认用第一个元素开始(start默认为0)。
var,同上。
<s:subset source="{‘one‘,‘two‘,‘three‘,‘four‘,‘five‘}" start="1" count="4">
...
</s:subset>
下面是使用subset标签遍历myList1中从索引1开始的两个元素。注意这里面的iterator必须放在iterator里面并且iterator不能配置其它属性。否则会出错。
<s:subset source="myList1" var="ff" start="1" count="2">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
7 date标签
date标签,用于格式化输出一个日期,除了可以直接格式化输出一个日期外,date标签还可以计算指定日期和当前时刻之间的时差。
format,可选属性,该属性指定的格式来格式化日期。
nice,这是一个可选属性,该属性只能为true或false,它用于指定是否输出指定日期和当前时刻之间的时差。默认为false不输出。
name,必填,该属性指定要格式化的日期值。
var,同上
<s:date name="#attr.now" format="dd/MM/yyyy" nice="true"/>
10 param标签
param标签主要用于向其他标签提供参数。param标签的属性:
name,可选属性,指定需要设置参数的参数名。
value,可选属性,指定需要设置参数的参数值。
param标签的两种写法:
<s:param name="color" value="blue"/>
<s:param name="color">blue</s:param>
11i18n
加载资源包到值堆栈,它允许text标志访问任何资源包的信息,而不只是当前action相管理的资源包。
value属性,取值为资源包的路径如:com.xxx.resources.AppMsg
例如,如果在资源包中存在:HelloWorld=Hello World!,下面将输出Hello World!
<s:i18n name="ApplicationMessages">
<s:text name="HelloWorld" />
</s:i18n>
12set
set标签赋予变量一个特定范围的值。当希望给一个变量赋一个复杂的表达式,每次访问变量而不是复杂的表达式时用到。
name,取值为字符串,表示变量的名字。
scope,取值为字符串,变量作用域,可以为application, session,request,page或action。
value,将会赋给变量的值。取值为Object或String。
如:<s:set name="bianliang" value="45"/>
13text
支持国际化信息的标签,国际化信息必须放在一个和当前action通过的resource bundle中,如果没有找到相应message,tag body将被当作默认message,如果没有tag body,message的name会被作为默认message。
例如上面的<s:text name="HelloWorld" />用于输出资源文件中的HelloWorld的值。
14property
<s:property />标签:是输出指定值用的标签。它的default属性时可选的,如果输出的属性值为null,则显示default属性指定的值。value也是可选属性,指定需要输出的属性值。如果没有指定该属性。则默认输出ValueStack栈顶的值。
request范围:<s:property value="#request.name"/>
session范围:<s:property value="#session.name"/>
application范围:<s:property value="#application.name"/>
<s:set name="foobar" value="#{‘foo1‘:‘bar1‘, ‘foo2‘:‘bar2‘}" />
<p>The value of key "foo1" is <s:property value="#foobar[‘foo1‘]" /></p>
使用property标签输出的指定的值,如果指定的值是javascript或html语句,这样的语句是不会被解析执行而是作为字符串输出来。
<s:property />取Map里面的值:
<s:property value="userTypeMap[‘key‘]" />
如果key是String型的则用引号包含,如果是整型则直接传入数值不要用引号包含。
如果key也是动态取得的则这样取,如:
<s:property value="userTypeMap[userInfoVO.userType]" />
15EL表达式
EL是Expresion Language的缩写,是表达式语言的意思。
el表达式最近最基本的语法格式就是$和{}。el表达式有四个隐含对象pageScope,requestScope,sessionScope,applicationScope。如果未指定scope,它的搜索顺序为:pageScope——>requestScope——>sessionScope——>applicationScope。
普通字符串
request.setAttribute("hello","hello world");
struts2标签输出:<s:property value="#request.name"/>
EL表达式输出:${requestScope.hello}或${hello}
Bean对象
Group group = new Group();
group.setName("尚学堂");
User user = new User();
user.setUsername("张三");
user.setAge(18);
user.setGroup(group);
user.setUserType("user");
EL表达式输出:${user.username}(输出group中的名称),${user.group.name}(输出group中的名称)
struts2标签输出:<s:property value="user.group.name"/>
Map对象
Map map=new HashMap();
map.put("my", "11mymymy");
map.put("my1", "22mymymy1");
EL表达式输出:${map.my1}结果为,22mymymy1。
Struts2标签输出:<s:property value="map[‘my‘]" />结果为11mymymy,因为key为字符串类型,所以需要用引号括起来,如果不是字符串类型可以不用引号。
如果Map中的key值是实体对象如:
map.put("user",user);
EL表达式输出:${map.user.password} //结果是user对象的password属性的值
struts2的标签输出<s:property value="map[‘user‘].password" />//结果是user对象的password属性的值
如果Map中的key也是动态取得的则这样取,如:
struts2标签输出:<s:property value="map[userVO.userName].userName" />//将输出张三,user对象的userName属性值。
EL表达式输出:${map[userVO.userName].userName}//将输出张三,user对象的userName属性值。
对于EL表达式,如果要动态取值时,就可以用“[]“来做,而“.“无法做到动态取值。例如:
${sessionScope.user[data]}中data 是一个变量。
注意如果Map的key是数字或带有空格,横杠等特殊字符串需要使用$map[‘特殊字符串‘]}这种形式,用单引号将其包括。
如Map map=new HashMap();
map.put("01", "11mymymy");
那么使用EL表达式${map.01}这样会报错,可以使用${map[‘01‘]}来取值,这样就不会报错了。
List对象
List list=new ArrayList();
list.add("one");
list.add(user);
EL表达式输出:
${list[0]}//将输出List中的第一个元素是字符串one。
${list[1].userName}//将user对象的userName属性的值。
Struts2标签输出:
<s:property value="list[0]" />//同上
<s:property value="list[1].userName" />//同上
数组对象
private int[] array={1,2,3,4,5,6,7,8};
EL表达式输出:${array[3]}
struts2标签输出:<s:property value="array[2]" />
Empty操作符(空值检查)
使用empty操作符来决定对象、集合或字符串变量是否为空或null。例如:
${empty param.username}
如果request的参数列表中的username值为null,则表达式的值为true。 EL也可以直接使用比较操作符与null进行比较。如${param.firstname == null}。
比较操作符 描述
==或eq 相等检查
!=或ne 不等检查
<或lt 小于检查
>或gt 大于检查
<=或le 小于等于检查
>=或ge 大于等于检查
算术运算符(+、-(二元)、*、/、div、%、mod)与逻辑运算符均(and、&&、or、||、!、not)与JAVA语言相同,不再列表。
条件运算符 ?=
${A?B:C } 如果A 为true 则返回B 否则返回 C
例如:
<select >
<option value="1" ${param.op==1 ? "selected" : ""}>选项一</option>
<option value="2" ${param.op==2 ? "selected" : "">选项二</option>
</select >
1+2: ${1+2 }<br>
10/5: ${10/5 }<br>
10 div 5: ${10 div 5 }<br>
10%3: ${10 % 3 }<br>
10 mod 3: ${10 mod 3 }<br>
使用EL表达式取值时,如果取出的值带有html标记,则html标记会被解释。
注意 <%@ page isELIgnored="true" %> 表示是否禁用EL语言,TRUE表示禁止.FALSE表示不禁止.JSP2.0中默认的启用EL语言。
EL表达式可以和C标签嵌套使用。例如:
<c:choose>
<c:when test="${data.irregularHeartBeat == 0}">
<input name="isNormal" value="" type="radio"> 有 <input name="" value="" type="radio" checked> 无</div>
</c:when>
<c:otherwise>
<input name="isNormal" value="" type="radio" checked> 有 <input name="" value="" type="radio"> 无</div>
</c:otherwise>
</c:choose>
如果使用EL表达式出现下面的异常,则需要将jsp-api.jar放在WEB-INF/lib下,然后重新保存文件既可以了
javax.servlet.jsp.pagecontext cantnot be resolved to a type
************************************