Struts2标签主要学习目标
Struts2框架的标签库可以分为以下三类:
用户界面标签(UI标签):主要用来生成HTML元素的标签。
表单标签:主要用于生成HTML页面的FORM元素,以及普通表单元素的标签。
非表单标签:主要用于生成页面上的tree,Tab页等。
非用户界面标签(非UI标签):主要用于数据访问,逻辑控制。
数据访问标签:主要包含用于输出值栈(ValueStack)中的值,完成国际化等功能的标签。
流程控制标签:主要包含用于实现分支,循环等流程控制的标签。
AJAX标签:用于支持Ajax效果
Struts2标签库
在早期的WEB开发中,JSP视图控制和显示技术主要依靠Java脚本来实现,这样一来,JSP页面重新嵌入了大量的Java脚本代码,给开发带来了极大的不方便。
从JSP1.1规范后,JSP增加了自定义标签库的支持。标签库是一种组件技术,通过标签库,可以将复杂的Java脚本代码封装在组件中,开发者只需要使用简单的代码就可以实现复杂的Java脚本功能。提供了Java脚本的复用性,提高了开发者的开发效率。
Struts2标签库相对struts1.x进行了巨大的改进,支持OGNL表达式,不再依赖任何表现层技术。
要在jsp中使用Struts2的标志,先要指明标志的引入。通过jsp的代码的顶部加入以下的 代码:
<%@taglib prefix="s" uri="/struts-tags" %>
属性具有类型,这些类型可以简单地分为字符串类型和非字符串类型,对于字符串类型的属
性,如果要访问动态数据,需要使用%{… }这样的语法,
例如:<s:include value=“%{ url }” />
Include标签的value属性是字符串类型,Struts2将对这个属性进行解析,查找符合%{…}样式
的字符串,然后将花括号之间的内容作为OGNL表达式进行求值。如果属性中没有%{…}样式
的字符串,那么属性的值将被直接看成是字符串数据。
例如:<s:include value=“urlTag.action” />
对于非字符串类型的属性值,将直接作为OGNL表达式进行求值。
例如:<s:property value=“username”/>
property标签的value属性是Object类型,它的值username将作为OGNL表达式进行求值,结
果是值栈中位于栈顶的对象的username属性的值。如果要为非字符串类型的属性直接指定字
符串数据,那么需要使用OGNL中的字符串常量,即用单引号(‘)或双引号(“)将字符
串括起来。
例如:<s:property value=“’zhangsan‘”/>
value属性的值‘zhangsan’作为字符串常量,计算结果就是zhangsan,因此输出zhangsan
在这种情况下,%{ }将被忽略,花括号中的内容将作为表达式被计算。
总结一下,struts2标签的属性按照下列的三个规则进行计算。
(1)所有的字符串属性类型都会解析“%{…}”这样的语法。
(2)所有的非字符属性类型都不会被解析,而是直接被看作一个OGNL表达式进行求值
(3)对于第二个规则的例外情况是,如果非字符串属性使用了“%{…}”语法,那么 %{…}将被忽略,花括号中的内容将作为表达式计算。
如果大家在使用标签时, 忘记了某个属性是字符串类型,还是非字符串类型,那么有一个简单的方法,那就是不考虑它是什么类型,统一使用“%{…}”语法。
控制标签和数据标签。控制标签用于呈现页面时控制执行流程,数据标签用于访问值栈中的数据。
数据标签:用于访问ActionContext和值栈中的数据。数据标签包括:
property set push param bean action include
url a i18n text date debug
控制标签:用于在呈现结果页面时控制程序的执行流程,根据程序执行的状态输出不同的结果,控制标签包括下列标签:
if/elseif/else iterator append merge
generator subset sort
数据标签-----property标签
property标签用于输出值栈中的对象的属性(property)值,使用value属性来指定要输出的对象属性,如果没有指定value属性,那么默认输出栈顶对象。
例如:<s:property value=“username” default=“游客” />
取出栈顶对象(通常是action)的username属性并输出,如果没有找到username属性,那么输出”游客”。
提升了性能(表达式的计算只有一次)
提高了代码的可读性。
Set标签以name属性的值作为键(key),将value属性的值保存到指定的范围对象中。属性scope取值中的page,request,session,application同JSP的4种范围,如果指定了action范围(默认值),value属性的值将被同时保存到request范围和OgnlContext中。
当使用param标签时, 参数的值可以通过value属性给出,也可以在标签体中给出(开始标签和结束标签之间的文本)。这二种用法有一些区别。我们看下面的例子:
<param name=“color”>blue</param> <!-- (1) -->
<param name=“color” value=“blue” /> <!-- (2) -->
在第(1)种情形中,参数值将作为java.lang.String对象(即字符串)被放入栈中;
在第(2)种情形中,参数值将作为表达式进行计算,如果blue不存在,则color参数的值为null。
在第(1)种情形中,要为color指定字符串值,可以写为:
<param name=“color” value=“ ‘ blue ‘ ”/>或者<param name=“color” value=“%{‘ blue ‘ }“/>
使用单引号包围字符串,表明这是一个字符串常量
注意:
id属性是可选的,无论是否指定id属性,bean标签创建的JavaBean实例都会被压入到值栈的顶部,在bean标签内部可以直接访问创建的对象,无须使用”#”标记,当bean标签结束的时候,bean标签创建的实例将从值栈中删除。
如果指定了id属性,那么bean标签创建的JavaBean实例还将被放到OgnlContext中,这样在bean标签的外部,也可以访问创建的对象了,不过此时就要使用”#”标记了
如果指定了id属性,则action将被放到OgnlContext中,在action标签结束后,可以通过#id来引用action.
include标签的标签体内可以包含多个param标签,用于向被包含的页面传递请求参数
<s:i18n name=“ApplicationResources”>
<s:text name=“title”/>
</s:i18n>
i18n标签将基名为ApplicationResources的资源包放入到值栈中,text标签从资源包中获取键 为title的文本消息。
注意:i18n标签放入值栈的资源包只能在i18n标签的标签体内访问,一旦i18n标签结束,值 栈中的资源包将被删除。
text标签也可以单独使用,在这种情况下,它将首先查找资源包的基名与调用的Action类名 相同的资源包。这意味着你可以在Action类所在的包中创建与Action类名相同的资源文件, 例如:在com.ibm.action包中有一个名为LoginAction的类, 你可以在com.ibm.action包括中 创建名为LoginAction.propertiesLoginAction_zh.properties、LoginAction_en.properties等 资源文件(名字中的LoginAction部分称为基名),当执行完LoginAction后,在转向的果页面 中使用单独的text标签获取本地化的文本消息,那么text标签将从 com.ibm.action.LoginAction_xx.properties(根据当前的语言环境选择某个资源文件)中读取 name属性值对应的文本消息。
注意:
1、format属性用于指定日期的格式化样式,具体的样式规则可java.text.SimpleDateFormat类的API文档。
2、将nice属性设为true,可以输出指定日期值和当前日期值之效,也就是说,当nice属性为true时,即使你指定了format属性
3、如果没有使用nice属性,也没有指定format属性,那么date查找struts.date.format键,并以这个键的值作为日期的格式化么默认将会使用DateFormat.MEDIUM格式化样式。
4、如果找不到name属性指定的Date对象,那么将返回空。
if:用于控制选择输出。
elseif:同if标签结合使用,用来控制选择输出。
else:同if标签结合使用,用来控制选择输出。
append:用来将多个集合拼接为一个新的集合。
generator:为一个字符串解析器,用来将一个字符串解析为一个集合。
iterator:迭代器,用来迭代输出集合数据。
merge:用来将多个集合拼接为一个新的集合,同append有所区别。
sort:用来对集合排序。
subset:用来截取集合的部分集合,开成新的集合子集合
该标签标准格式如下:
<s:if test=“表达式”>
……..
</s:if>
<s:elseif test=“表达式”>
……..
</s:elseif>
<s:else>
………..
</s:else>
<!-- 定义一个testname属性 -->
<s:set name="testname" value="%{'Java'}" />
<!-- 使用if标签判断-->
<s:if test="%{#testname=='Java'}">
<div>
<s:property value="%{# testname}" />
</div>
</s:if>
<s:elseif test="%{#testname=='Jav'}">
<div>
<s:property value="%{# testname}" />
</div>
</s:elseif>
<s:else>
<div>
testname不是“Java”
</div>
</s:else>
<s:set name="age" value="61"/>
<s:if test="${age > 60}">
老年人
</s:if>
<s:elseif test="${age > 35}">
中年人
</s:elseif>
<s:elseif test="${age > 15}" id="wawa">
青年人
</s:elseif>
<s:else>
少年
</s:else>
<s:set name="name" value="<%="'"+ request.getParameter("name")+"'" %>"/>
<%
System.out.println(request.getParameter("name"));
%>
<s:if test="#name=='zhaosoft'">
zhaosoft here
</s:if>
<s:elseif test="#name=='zxl'">
zxl here
</s:elseif>
<s:else>
other is here
</s:else>
描述:用于遍历集合(java.util.Collection)List,Map,数组或枚举值(java.util.iterator)。
IteratorStauts实例包含方法
int getCount():返回当前迭代过元素的总数。
int getIndex():返回当前迭代元素的索引。
boolean isEven():判断当前迭元素是否为偶数。
boolean isOdd():判断当前迭元素是否为奇数。
boolean isFirst():判断当前迭元素是否为第一个元素。
boolean isLast():判断当前迭元素是否为最后一个元素
IteratorStauts的这些方法分别对应了count,index,even,odd,first,last属性
<p>day is: <s:property/></p>
</s:iterator>
private List myList;
private Map myMap;
public String execute() throws Exception {
myList = new ArrayList();
myList.add("第一个元素");
myList.add("第二个元素");
myList.add("第三个元素");
myMap = new HashMap();
myMap.put("key1", "第一个元素");
myMap.put("key2", "第二个元素");
myMap.put("key3", "第三个元素");
return SUCCESS;
}
省略生成setter/getter方法
<table>
<s:iterator value="{'第一个元素','第二个元素'}" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
<h2>显示List属性</h2>
<table>
<s:iterator value="myList" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
<h2>显示Map</h2>
<table>
<s:iterator value="#{'key1':'第一个元素','key2':'第二个元素'}" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
<h2>显示Map属性</h2>
<table>
<s:iterator value="myMap" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
private List myList1, myList2;
private Map myMap1, myMap2;
public String execute() throws Exception {
myList1 = new ArrayList();
myList2 = new ArrayList();
myList1.add("第一个集合#第一个元素");
myList1.add("第一个集合#第二个元素");
myList1.add("第一个集合#第三个元素");
myList2.add("第二个集合#第一个元素");
myList2.add("第二个集合#第二个元素");
myList2.add("第二个集合#第三个元素");
myMap1 = new HashMap(); myMap2 = new HashMap();
myMap1.put("key1", "第一个集合#第一个元素");
myMap1.put("key2", "第一个集合#第二个元素");
myMap1.put("key3", "第一个集合#第三个元素");
myMap2.put("key1", "第二个集合#第一个元素");
myMap2.put("key2", "第二个集合#第二个元素");
myMap2.put("key3", "第二个集合#第三个元素");
return SUCCESS;
} //省略setter/getter方法
<h1><span style="background-color: #FFFFcc">Append标签示例</span></h1>
<h2>拼接List属性</h2>
<table>
<s:append id="newList">
<s:param value="myList1" />
<s:param value="myList2" />
</s:append>
<s:iterator value="#newList" id="name" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
<h2>拼接Map属性</h2>
<table>
<s:append id="newMap">
<s:param value="myMap1" />
<s:param value="myMap2" />
</s:append>
<s:iterator value="#newMap" status="st">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
该标签的属性如下:
id:指定了集合元素的ID。
count:可选属性,为一个Integer类型值,指定生成集合中元素的总数。
separator:必填属性,为一个String类型值,指定用来分解字符串的分隔符。
val:必填属性,为一个String类型值,指定被分解的字符串。
converter:可选属性,为一个Converter类型实例,指定一个转换器,该转换器负
责将集合中的每个字符串转换为对象。
控制标签----- generator标签举例
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String execute() throws Exception {
setMsg("第一个元素;第二个元素;第三个元素");
return SUCCESS;
}
<span style="background-color: #FFFFCC">Generator标签示例</span>
</h1>
<table>
<s:generator separator=";" val="msg" id="temp" count="2"></s:generator>
<s:iterator status="st" value="#attr.temp">
<tr>
<td><s:property value="#st.getIndex()" /></td>
<td><s:property /></td>
</tr>
</s:iterator>
</table>
注意:如果在generator标签中指定了count属性,则该集合中最多只能有count个元素,多余的元素将会被忽略。
控制标签----- append标签
append:用来将多个集合拼接为一个新的集合。
form标签本身的行为不同于它内部的元素。
Struts2表单标签包括下列标签:
form textfield password radio checkbox checkboxlist select
doubleselect combobox optiontransferselect optgroup updownselect
textarea hidden file label reset submit token head
表单标签的name和value属性
很多表单标签(form标签除外)的name属性和value属性之间存在一个独特的关系。name属性除了为HTML表单元素指定名字,在表单提交时作为请求参数的名字外,同时它还映射到Action的属性。 在大多数情况下,name属性映射到一个简单的JavaBean属性,例如name属性的值为”postalCode”,在表单提交后,struts2框架将会调用Action的setPostalCode()方法来设置属性。 有的时候你希望在表单元素中显示Action属性的数据,这时就轮到value属性登场了,为value属性指定表达式”%{postalCode}”,这将会调用Action的getPostalCode()方法,并在表单中显示返回的数据,之后, 用户可以编辑这个值,然后重新提交它。
1)通常情况下,当前输出表单的请求和提交表单的请求属于同一个命名空间。
例如:请求/admin/updateCategory!default.action输出的表单,命名空间会被假设为/admin,因此在
使用form标签时,可以不使用namespace属性。如下:
<s:form action=“updateCategory” >
如果输出表单的请求和提交表单的请求分属于不同的名称空间,那么可以通过
namespace属性指定处理表单提交的action所属的名称空间。
2)若通过action的一个非execute方法输出表单,然后将表单提交给action默认的execute方
法执行,那么form标签的action属性可以忽略。例如:对于下面的表单:
<s:form >
<s:textfield name=“username” label=“用户名”/>
<s:submit />
</s:form>
当访问/register!default.action时, 输出上表单,form标签会自动将action属性设为 register,这样在表单提交后就会执行action的execute方法。
3)method和enctype是HTML form标签的属性。
4)当使用验证框架时,将form标签的validate属性设为true,将自动生成客户端的JavaScript验证代码。
<s:form action=“register” method=“post” /> struts2默认的主题是xhtml,上述代码在客户端浏览器中的输出如下:
<s:form id=“register” οnsubmit=“return true” action=“register” method=“post”>
<table class=“wwFormTable”></table>
</s:form>
可以看到form标签内部输出了一个table元素。
看下面的代码:
<s:form action=“register” method=“post”>
<s:textfield name=“username” label=“用户名” />
</s:form>
例子:<s:password name=“password” label=“密码” />
例子:
<s:textarea name=“personal” cols=“30” rows=“5” label=“个人简历” />
<select …><option..></option></select>
<s:form>
<s:select label=“最高学历” name=“education” list=“{‘高中’,‘大学’,‘硕士’}”
/>
</s:form>
在select标签的list属性中直接使用OGNL表达式创建了一个列表,列表中的每一项都将作为
HTML列表框的一个选项。
示例二:
<s:form>
<s:select label=“最高学历” name=“education” list=“#{1:‘高中’,2:‘大学’,3:‘硕士
’}” />
</s:form>
在select标签的list属性中直接使用OGNL表达式创建了一个Map。在这里要注意的是,Map的key是作为列表框选项的值,而Map中的value是作为列表框选项的内容。
示例三:
<s:form>
<s:select label=“最高学历” name=“education” list=“{‘高中’,‘大学’,‘硕士
’}” headerKey=“-1” headerValue=“请选择你的学历” />
Header选项主要用来越提示作用,因此应该将header选项的值(通过headerKey属性设置)
设为无意义的值,例如此处的-1.
示例四:
<s:form>
<s:select label=“最高学历” name=“education” list=“{‘高中’,‘大学’,‘硕士
’}” headerKey=“-1” headerValue=“请选择你的学历” emptyOption=“true”
multiple=“true” / >
使用emptyOption属性在header选项后添加一个空的选项。
multiple属性设为false,则只能从下拉列表中选择一个选项,如果设为true,则可以多选。
使用一个或者多个optgroup标签,对选项进行逻辑分组。注意, optgroup标签本身不能嵌套。
例子:
<%@ taglib prefix=“s” uri=“/struts-tags” %>
<s:form>
<s:select label="选择图书" name="book" list="#{1:'JAVA核心编程',2:'深入struts2学习'}" >
<s:optgroup label="C/C++图书" list="#{3:'VC++编程详解',4:'Spring详解'}"/>
<s:optgroup label="Oracle图书" list="#{5:'Oracle基础',6:'DBA入门'}"/>
</s:select>
</s:form>
optgroup标签注意
optgroup标签的label属性指定选项组的组名。 optgroup标签对应的模板需要使用listKey和listValue属性的值,因此你要么为list属性指定一个Map类型的值(此时,listKey默认为Map.Entry的key,listValue默认为Map.Entry的value),要么为list属性指定一个对象列表,然后使用listKey和listValue属性指定对象的属性作为选项的值和内容
例子:
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:form>
<s:radio name="user.sex" value="1" list="#{1 : '男', 0 : '女'}" label="性别" />
</s:form>
注意,除非你知道你要做什么,否则不要将fieldValue属性设置为false。将fieldValue属性设置为false可能会导致一些问题。HTML规范规定,复选框只有在选中时才会被提交,在通常的Servlet/JSP处理过程中,我们可以通过判断复选框的name属性所指定的请求参数是否存在来获知用户是否选中了复选框,如果选中,则取出它的值。然而,在使用struts2框架时,这一切发生了一些微妙的变化。如果将fieldValue属性设置为false,那么复选框的值将是false。当没有选中复选框时,提交的请求参数中不会有复选框对应的请求参数。不过,虽然struts2框架没有接收到这个请求参数,但它仍然会将复选框对应的action属性的值设为false。于是你就会看到一个奇怪的现象,那就是不管你是否选中复选框,对应的action属性的值都是false.
似,只是创建的是HTML复选框。不同的是, checkboxlist标签是多选标签。
示例:
<s:form>
<s:checkboxlist name="interest" list="{'足球','篮球','排球','游泳'}" label="兴趣爱好"/>
</s:form>
示例: <s:hidden name=“id” value=“5” />
input:等价于HTML代码<input type=“submit”…>
image:等价于HTML代码<input type=“image”…>
button:等价于HTML代码<input type=“submit”…>
HTML的button标签已经演进为可以分别指定提交的值(通过value属性指定)和按钮上显 示的文本(通过标签的内容来指定),但只能用于IE6.0以上版本的浏览器。
submit标签示例
例1:指定image类型的提交按钮,使用method属性。
<s:submit type=“image” method=“login” src=“images/login.gif” />
上述代码在客户端浏览器中的输出如下:
<input type=“image” src=“images/login.gif” name=“method:login” value=“Submit”…./>
注意生成的input元素的name属性。
例2:指定button类型的提交按钮,使用action和method属性。
<s:submit type=“button” action=“userManager” method=“login” label=“登录” />
上述代码在客户端浏览器中的输出如下:
<button type=“submit” name=“action:userManager!login” value=“submit” …/> 登录</button>
注意button标签的name属性。
通过上面的例子可以看到name属性有二个前缀:method和action,这是struts2提供的一种特性,即使 用一些预定义的前缀来命名一个按钮,通过按钮的名字来改变执行的行为。Struts2定义了4个前缀 ,如下:
action--------action:userManager
redirect------redirect:cancel.jsp
redirection-action------redirect-action:register
用户注册和登录,那么可以编写代码如下:
<s:form action=“userManager”>
<s:textfield label=“用户名” name=“user.username” />
<s:password label=“密码” name=“user.password” />
<s:submit value=“登录” name=“method:login” />
<s:submit value=“注册” name=“method:reg” />
</s:form>
注意:1)对于input类型的提交按钮,不能通过submit标签的label属性来设置提交按钮上的文本,只能使用value属性。
2)可以在submit标签的name属性中直接使用method前缀,也可以像前面给出的例子中使用submit标签的method属性来指定处理请求的action方法。
示例:
<s:form action=“login”>
<s:textfield label=“用户名” name=“user.username” />
<s:password label=“密码” name=“user.password” />
<s:submit value=“登录” />
<s:submit value=“注册” name=“action:register” />
</form>
如果用户已经注册,可以直接登录,否则单击注册按钮,转到注册页面。action前缀也可以和struts2的动态方法调用结合使用,