-
Struts2标签库
Struts2提供了一套s标签库,该标签库分:表单标签、控制标签、数据标签等。
1.导入标签库
<%@ taglib prefix=”s” uri=”/struts-tags” %> |
prefix属性值是使用此标签库的前缀。
2.控制标签
<s:if><s:elseif><s:else>标签
作用:用于控制选择输出。
<s:if test=”表达式1”> 标签体 </s:if> <s:elseif test=”表达式2” > 标签体 <s:else > 标签体 </s:else >
<s:if test=”%{false}”> </s:if> <s:if test=”name==’张三’”> </s:if> |
3.<s:iterator>迭代标签
var属性:它的取值就是一个普通的字符串.
用了var:把每次遍历的对象作为value,把var的值作为key,存入ContextMap中
没用var:把每次遍历的对象压入栈顶,再下次遍历之前弹栈(从栈顶移走)。
begin:开始遍历的索引
end:遍历的结束索引
step:遍历的步长。
status:计数器对象
count 已经遍历的集合元素个数
index 当前遍历元素的索引值
odd 是否奇数行
even 是否偶数行
first 是否第一行
last 是否最后一行
//for循环 <s:iterator begin="1" end="10" step="1" var="i"> <s:property value="i"/> </s:iterator> //迭代数组元素 <s:iterator value="{1,2,3,4,5,6}" var="i"> <s:property value="i" /> </s:iterator> //迭代对象(property放对象属性名) <s:iterator value=”user”> <s:property value=”uname” /> <s:property value=”uesr.upwd” /> </s:iterator> //迭代集合(简单类型,如String) <s:iterator value=”list”> <s:property /> </s:iterator> <s:iterator value=”list” var=”i”> <s:property var=”i”/> </s:iterator>
//List(自定义对象属性) public String execute(){ List<UserInfo> list = new ArrayList<UserInfo>();
UserInfo userInfo = new UserInfo(); userInfo.setUsername("u1"); userInfo.setPassword("p1"); userInfo.setRoleInfo(new RoleInfo("r1"));
userInfo = new UserInfo(); userInfo.setUsername("u2"); userInfo.setPassword("p2"); userInfo.setRoleInfo(new RoleInfo("r2")); list.add(userInfo); list.add(userInfo); } <s:iterator value="list" var="var"> <s:property value="#var.username"/> <s:property value="#var.password"/> <s:property value="#var.roleInfo.rolename"/><br> </s:iterator> 或者: <s:iterator value="list"> <s:property value="username"/> <s:property value="password"/> <s:property value="roleInfo.rolename"/><br> </s:iterator>
//Map(普通属性) public String execute(){ Map<String,String> map = new HashMap<String,String>(); map.put("k1", "v1"); map.put("k2", "v2"); }
<s:iterator value="map" var="var"> <s:property value="#var.key"/> <s:property value="#var.value"/><br> </s:iterator> 或者: <s:iterator value="map"> <s:property value="key"/> <s:property value="value"/><br> </s:iterator>
//Map(自定义对象属性) public String execute(){ Map<String, UserInfo> map = new HashMap<String, UserInfo>(); UserInfo userInfo = new UserInfo(); userInfo.setUsername("u1"); userInfo.setPassword("p1"); userInfo.setRoleInfo(new RoleInfo("r1"));
userInfo = new UserInfo(); userInfo.setUsername("u2"); userInfo.setPassword("p2"); userInfo.setRoleInfo(new RoleInfo("r2"));
map.put("k1", userInfo); map.put("k2", userInfo); } <s:iterator value="map" var="var"> <s:property value="#var.key"/> <s:property value="#var.value.username"/> <s:property value="#var.value.password"/> <s:property value="#var.value.roleInfo.rolename"/><br> </s:iterator> 或者 <s:iterator value="map"> <s:property value="key"/> <s:property value="value.username"/> <s:property value="value.password"/> <s:property value="value.roleInfo.rolename"/><br> </s:iterator>
//Map嵌套Map(自定义对象属性) public String execute(){ Map<String, Map<String,UserInfo>> map = new TreeMap<String,Map<String,UserInfo>>(); Map<String,UserInfo> innerMap = new TreeMap<String,UserInfo>(); UserInfo userInfo = new UserInfo(); userInfo.setUsername("u1"); userInfo.setPassword("p1"); userInfo.setRoleInfo(new RoleInfo("r1")); userInfo = new UserInfo(); userInfo.setUsername("u11"); userInfo.setPassword("p11"); userInfo.setRoleInfo(new RoleInfo("r11")); innerMap.put("k1", userInfo); innerMap.put("k11", userInfo); map.put("key1", innerMap); // innerMap = new TreeMap<String,UserInfo>(); userInfo = new UserInfo(); userInfo.setUsername("u2"); userInfo.setPassword("p2"); userInfo.setRoleInfo(new RoleInfo("r2")); userInfo = new UserInfo(); userInfo.setUsername("u22"); userInfo.setPassword("p22"); userInfo.setRoleInfo(new RoleInfo("r22")); innerMap.put("k2", userInfo); innerMap.put("k22", userInfo); map.put("key2", innerMap); } <s:iterator value="map" var="var"> <s:iterator value="value"> <s:property value="#var.value"/>
<s:property value="key"/> <s:property value="#var.key"/>
<s:property value="value.username"/> <s:property value="value.password"/>
<s:property value="value.roleInfo.rolename"/> </s:iterator> |
4.<s:sort>排序标签
准备工作:
- 创建排序规则类,如StudentSort
<!--实例化排序规则类--> <s:bean name="com.zking.StudentSort" id="cmp"/> --StudentSort cmp = new StudentSort();
<!--source="studentList"为数据源,集合--> <s:sort comparator="cmp" source="studentList" id="sort"> <s:iterator> <s:property value="name"/> <s:property value="age"/> </s:iterator> </s:sort> |
5.<s:append>标签
作用:用于将多个集合拼成一个新的集合
案例1:
<s:append id="books"> <s:param value="{'C语言程序设计','数据结构与算法','数据库系统概论'}"></s:param> <s:param value="{'Java语言程序设计','计算机组成原理','操作系统教程'}"></s:param> </s:append>
<table border="1" cellspacing="0" > <s:iterator value="#books" status="st"> <tr> <td><s:property value="#st.count"/></td> <td><s:property/></td> </tr> </s:iterator> </table> |
结果:
案例2:
Action类
public class AppendTagAction extends ActionSupport{ private List<String> list1 = new ArrayList<String>(); private List<String> list2 = new ArrayList<String>(); private List<String> list3 = new ArrayList<String>(); private Map<String,String> map1 = new HashMap<String,String>(); private Map<String,String> map2 = new HashMap<String,String>(); private Map<String,String> map3 = new HashMap<String,String>(); @Override public String execute() { list1.add("List1 - 1"); list1.add("List1 - 2"); list1.add("List1 - 3");
list2.add("List2 - 1"); list2.add("List2 - 2"); list2.add("List2 - 3");
list3.add("List3 - 1"); list3.add("List3 - 2"); list3.add("List3 - 3");
map1.put("map1-key1", "map1-value1"); map1.put("map1-key2", "map1-value2"); map1.put("map1-key3", "map1-value3");
map2.put("map2-key1", "map2-value1"); map2.put("map2-key2", "map2-value2"); map2.put("map2-key3", "map2-value3");
map3.put("map3-key1", "map3-value1"); map3.put("map3-key2", "map3-value2"); map3.put("map3-key3", "map3-value3");
return SUCCESS; } //getter methods... } |
View:
<!--拼接List集合--> <s:append var="customListIterator"> <s:param value="%{list1}" /> <s:param value="%{list2}" /> <s:param value="%{list3}" /> </s:append> <!--遍历拼接后的List集合--> <s:iterator value="%{#customListIterator}"> <li><s:property /></li> </s:iterator>
<!--拼接Map集合--> <s:append var="customMapIterator"> <s:param value="%{map1}" /> <s:param value="%{map2}" /> <s:param value="%{map3}" /> </s:append> <!--遍历拼接后的Map集合--> <s:iterator value="%{#customMapIterator}"> <li><s:property /></li> </s:iterator>
<!--拼接List + Map集合--> <s:append var="customMixedIterator"> <s:param value="%{list1}" /> <s:param value="%{map1}" /> </s:append> <!--遍历拼接后的集合--> <s:iterator value="%{#customMixedIterator}"> <li><s:property /></li> </s:iterator> |
6.数据标签
<s:action>标签
作用:直接从JSP页面中调用Action,如果“executeResult=true”,则该标签会把Action的处理结果(即视图资源)包含到本页面中。
<s:action name="hello" executeResult="true" /> |
Action:
public class TestAction extends ActionSupport { @Override public String execute() throws Exception { // TODO Auto-generated method stub return "abc"; } } |
Struts.xml配置:
<action name="hello" class="com.zking.action.HelloWorldAction" > <result name="abc">/helloWorld.jsp</result> </action> |
把TestAction中的execute()方法的结果码对应的视图资源(helloWorld.jsp)包含到当前页面中。
其它写法:
<s:action name="actionTagAction!specialMethod" executeResult="true" />
<!--向Action传递参数--> <s:action name="modle_show" namespace="/webs" executeResult="true"> <s:param name="name" value='1'></s:param> </s:action> |
7.<s:propert>标签
id:可选属性,指定该元素的标识。
default:可选属性,如果要输出的属性值为null,则显示default属性的指定值。
escape:可选属性,指定是否忽略HTML代码。
value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出ValueStack栈顶的值
<%-- 输出值栈中的值 --%> <s:property value="custName"/> |
8.<s:bean>标签
作用:实例化一个对象。
<s:bean name="com.zking.Student" id="stu">
第一种赋值方式: <!-- 设置name为张三,年龄为19 --> <s:param name="name">张三</s:param> <s:param name="age">19</s:param> <!-- 读取bean中的值 --> <s:property value="name"/> <s:property value="age"/>
第二种赋值方式: <!-- 该方法为参数赋值时必须加引号 --> <s:param name="name" value="'李四'"></s:param> <s:param name="age" value="'20'"></s:param> <!-- 读取bean中的值 --> <s:property value="name"/> <s:property value="age"/> </s:bean>
在bean标签外利用id取值: <s:property value="#stu.name"/> <s:property value="#stu.age"/> |
9.表单标签
<s:form>表单
action 指定提交时对应的action,不需要action后缀
enctype HTML表单enctype属性
method HTML表单method属性
namespace 所提交action的命名空间
<s:form action="register" method=”post” namespace=""> …… </s:form> |
<s:textfield>文本框
maxlength 文本输入控件可以输入字符的最大长度
readonly 当该属性为true时,不能输入
size 指定可视尺寸
id 用来标识元素的id。在ui和表单中为HTML的id属性
name 控件名称
label 控件文字符
<s:textfield name="username" label="用户名"></s:textfield> |
<s:password>密码框
<s:password name="password" label="密码"></s:textfield> |
<s:textarea>文本域
cols 列数
rows 行数
readonly 当该属性为true时,不能输入
wrap 指定多行文本输入控件是否应该换行
id 用来标识元素的id。在ui和表单中为HTML的id属性
<s:textarea name="personal" cols="10" rows="5" label="个人简历"></s:textarea> |
<s:select>下拉框
//使用name和list属性,list属性的值是一个列表 <s:select label="最高学历" name="education" list="{'高中','大学','硕士','博士'}"/>
//使用name和list属性,list属性的值是一个Map <s:select label="最高学历" name="education" list="#{1:'高中',2:'大学',3:'硕士',4:'博士'}"/>
//使用headerKey和headerValue属性设置header选项 <s:select label="最高学历" name="education" list="{'高中','大学','硕士','博士'}" headerKey="-1" headerValue="请选择您的学历"/>
//使用emptyOption属性在header选项后添加一个空的选项 <s:select label="最高学历" name="education" list="{'高中','大学','硕士','博士'}" headerKey="-1" headerValue="请选择您的学历" emptyOption="true"/>
//使用multiple属性设置多选 <s:select label="最高学历" name="education" list="{'高中','大学','硕士','博士'}" headerKey="-1" headerValue="请选择您的学历" emptyOption="true" multiple="true"/>
//使用size属性设置下拉框可显示的选项个数 <s:select label="最高学历" name="education" list="{'高中','大学','硕士','博士'}" headerKey="-1" headerValue="请选择您的学历" emptyOption="true" multiple="true" size="8"/>
//使用listKey和listValue属性,利用Action实例的属性(property)来设置选项的值和选项的内容 <s:select label="最高学历" name="education" list="educations" listKey="id" listValue="name"/> |
<s:doubleselect>级联列表框
<s:doubleselect label="请选择所在省市" name="province" list="{'四川省','山东省'}" doubleName="city" doubleList="top == '四川省' ? {'成都市', '绵阳市'} : {'济南市', '青岛市'}" />
<s:doubleselect label="请选择所在省市"
name="province" list="provinces" //要迭代的集合 listKey="id" //指定集合中的id属性作为选项的value listValue="name" //指定集合中的name属性作为选项的内容
doubleList="cities" //要迭代的集合 doubleListKey="id" //指定集合中的id属性作为选项的value doubleListValue="name" //指定集合中的name属性作为选项的内容 doubleName="city" //指定第二个列表框的city映射
headerKey="-1" //选择header时选择的value headerValue="---------- 请选择 ----------" emptyOption="true" />
|
<s:checkbox>复选按钮与<s:checkboxlist>复选按钮组
<!--复选按钮--> <s:checkbox name="love" value="true" label="是否有兴趣" fieldValue="是" /> <!--复选按钮组--> <s:checkboxlist name="love" list="{'足球','篮球','排球','游泳'}" label="兴趣爱好"/> |
<s:radio>单选框
<s:radio label="性别" name="sex" list="genders" value="女" />
<s:radio label="回答" name="answer" list="#{'1':'Yes','2':'No'}" value="2" /> |
<s:token>盾牌
<s:token></s:token> |
经典案例:<s:token>防止用户重复提交
原因:当用户填写完表单提交后,若再次操作点击提交、刷新页面、提交页面后退按钮,都会导致表单重复提交。
解决办法:session Token机制,即在<form>表单中添加<s:token>
当用户首次访问表单页面时,服务器会做三件事:
- 创建一个session对象。
- 通过<s:token>产生一个随机数,并保存在session中。
- 服务器把产生的随机数发送给客户端。
当用户向服务器提交表单时,此时服务器会做:
- 判断从客户端发送过来的请求参数中的随机数和保存在session对中随机数是否相等,如果相等,则认为是第一次提交。
- 若是第一次提交,服务器会把原来保存在session的随机数改变成其他的随机数。发给客户端的随机数不变。
- 因为在第一次提交表单后,服务器随机数和客户端的不一样了,所以当重复提交的时候,服务器看到客户端的随机数和自己的不一样了,就可以判断这是在重复提交了。
重点代码:
<s:form action="token" theme="simple"> username:<s:textfield name="username"></s:textfield> password:<s:password name="password"></s:password> <s:submit value="submit"></s:submit> <!--服务器通过token标签 来产生盾牌随机数--> <s:token></s:token> </s:form> |
Struts.xml
<action name="token" class="com.struts2.TokenAction"> <!--设置第一次提交跳转页面--> <result name="success">/success.jsp</result> <!--设置重复提交时跳转页面--> <result name="invalid.token">/invalid.jsp</result> <!--设置盾牌拦截器--> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> |
<s:file>文件选择
<s:file name="uploadFile" label="选择文件"/> |
参见后面的文件上传。
<s:hidden>标签
<s:hidden name="id" value="5"/> |
<s:submit>按钮
Type 按钮类型,有image\button
Method 提交调用方法
value 按钮文本
Src 图片引用路径
<s:submit value="登陆"></s:submit> 页面渲染: <input type="submit" value="提交" id="test_0"/>
<!--提交到Action中的say()--> <s:submit value="登陆" method="say"></s:submit>
<!--图片按钮--> <s:submit type="image" method="login" src="images/login.jpg"></s:submit> 页面渲染: <input type="image" alt="Submit" src="images/login.jpg" id="user__login" name="method:login" value="Submit"/> |
表单案例
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>注册界面</title> </head> <body> <s:form action="register" namespace="/"> <s:textfield name="username" label="用户名" key="abc"/> <s:password name="password" label="密码"/> <s:radio name="sex" label="性别" list="#{'0':'男','1':'女'}" value="0" /> <s:textfield name="age" label="年龄"/> <s:select name="city" list="#{'bj':'北京','sh':'上海','gz':'广州','sz':'深圳'}" label="城市" headerKey="-1" headerValue="---请选择城市---" emptyOption="true"/> <s:checkboxlist name="hibbies" list="#{'code':'写代码','algorithm':'算法','movie':'电影'}" label="爱好"/> <s:checkbox name="married" label="是否已婚" value="true" labelposition="left" /> <s:textarea name="description" label="自我介绍" rows="5" cols="20"/> <s:file name="phone" label="头像"/> <s:submit value="提交"/> <s:reset value="重置"/> </s:form> </body> </html> |