property标签
•property标签用于输出值栈中的对象的属性值,使用value属性来指定要输出的对象属性,如果没有指定value属性,那么默认输出栈顶对象。
属性如下:
例子:
<s:property value="username" default="游客"/>
取出栈顶对象(通常是action)的username 属性并输出,如果没有找到username属性,那么输出“游客”。
详细例子:
package com.struts; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.entity.Users; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; /** * 控制器类 * 作用:处理客户端的请求 * @author asus * */ public class PropertyAction extends ActionSupport { /** 成员变量:值栈中属性 */ private Users user; /** 重写execute方法 */ public String execute(){ /** 给成员变量赋值 */ user= new Users(); user.setName("admin"); user.setPassword("q12345"); /** 局部变量:非值栈中属性 */ Users userTow=user; String amp="&"; String str="ABCD"; String num="1"; List<Users> list=new ArrayList<Users>();//集合中装了两个对象 list.add(user); list.add(userTow); /** 将局部变量存入request范围里 */ Map<String, Object> request=(Map<String, Object>) ActionContext.getContext().get("request"); request.put("userTow", userTow); request.put("amp", amp); request.put("str", str); request.put("num", num); request.put("list", list); return SUCCESS; } /** JavaBean */ public Users getUser() { return user; } public void setUser(Users user) { this.user = user; } }
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <body> <h1> 结果页面 </h1> <!-- property标签基本用法 --> <!-- 取值栈中的属性(Action中的成员属性) 需要生成Get,Set方法,不需要加范围与井号 --> 结果1: <s:property value="user.name" default="若value属性中没有取到值则输出此内容。" /> <br> <!-- 取非值栈中的属性(除了Action中的成员属性外) 需要加井号,与在获取request/session/application/attr/parameters这五个范围时,需要明确指定范围 --> 结果2: <s:property value="#request.userTow.password" /> <br> <!-- escape:是否转译 true:表示将value内的内容强制转换成字符串显示 如&会被转换为& false:表示将value值当做html代码去解析 会被被解析为& --> 结果3: <s:property value="#request.amp" escape="true" /> hearts; <br> 结果4:<!-- 这里结果为桃心符号 --> <s:property value="#request.amp" escape="false" /> hearts; <br> <!-- property标签灵活用法 --> <!-- value参数的类型是object,可以理解为这个默认是会解析成ognl表达式的 比如需要输入一个字符串string,在value里面的字符串string外面加了单引号,这样不会将string解析成ognl表达式了 --> 结果5: <s:property value="'user'" /> <br> <!-- 故value的值解析成OGNL表达式,在此表达式内,有些对象的值的使用与java代码相似,但不相同,以下取几个例子 --> 结果6: <s:property value="#request.str.length()" /> <br> 结果7: <s:property value="#request.str.substring(1,3)" /> <br> <!-- value内还可以写表达式,比如输出一个整型变量num的+1值 --> 结果8: <s:property value="#request.num+1" /> <br> <!-- value内为List集合时,取其长度 --> 结果9: <s:property value="#request.list.size" /> <br> <!-- value内为List集合时,取其内容 --> 结果10: <s:property value="#request.list.get(0).name" /> </body>
例子页面输出结果:
set标签
•Set标签将一个值赋给指定范围内变量。Set标签在某些情况下是比较有用的,例如在页面中多次引用一个复杂的表达式,我们可以将这个表达式赋给一个变量,然后直接引用变量。带来的好处就是:
–提升了性能(表达式的计算只有一次)
–提高了代码的可读性。
属性如下:
例子:
<!-- 使用bean标签定义一个javaBean实例 --> <s:bean name="lee.Person" id="p"> <s:param name="name" value="zhangsan" /> <s:param name="age" value="29" /> </s:bean> 将p放入默认范围内 <s:set value="#p" name="test" /> <s:property value="#test.name" /> <br> <s:property value="#test.age" /> <br> 将p放入application范围内。 <s:set value="#p" name="test" scope="application" /> <s:property value="#attr.test.name" /> <br> <s:property value="#attr.test.age" /> <br> 将p放入session范围内。 <s:set value="#p" name="test" scope="session" /> ${sessionScope.test.name} <br> ${sessionScope.test.age} <br>
详细例子:
package com.struts; import com.entity.Users; import com.opensymphony.xwork2.ActionSupport; /** * 控制器类 * 作用:处理客户端的请求 * @author asus * */ public class SetAction extends ActionSupport { /** 成员变量:值栈中属性 */ private Users user; /** 重写execute方法 */ public String execute(){ /** 给成员变量赋值 */ user = new Users(); user.setName("admin"); return SUCCESS; } /** JavaBean */ public Users getUser() { return user; } public void setUser(Users user) { this.user = user; } }
<%@ taglib uri="/struts-tags" prefix="s"%> <body> <!-- set标签 --> <h1> set标签 </h1> <p> 将Action中成员属性:user.name的值保存到默认范围中,即Stack Context(application) </p> <s:set name="name" value="user.name" /> <!-- <s:property value="#application.name" />这种写法取不到值 --> <s:property value="#name" /> <s:property value="#attr.name" /> <p> 当指定范围类型application </p> <s:set name="nameTow" value="user.name" scope="application" /> <!-- <s:property value="#nameTow" />这种写法取不到值 --> <s:property value="#attr.nameTow" /> <s:property value="#application.nameTow" /> <p> 小结:set标签默认范围是application。 当刻意去指定范围为application时,虽然范围相同,但他们取值方式又有略微不同。 <br> 共通点:都可以使用attr <br> 区别: <br> 1)默认不指定范围的方式,取值可以不加范围标志,不能使用application范围标志打点取值。 <br> 2)指定application的方式,取值必须要加范围标志,但可以使用application范围标志打点取值。 <br> </p> </body>
例子页面输出结果:
push标签
•push标签用于把一个值压入值栈(位于栈顶),注意和set标签的区别,set标签是将值放到action上下文中。当push标签结束后,push标签放入值栈中的对象将被删除,换句话说,要访问push标签压入栈中的对象,需要在标签内部去访问。
属性如下:
<!-- 使用bean标签创建一个JavaBean实例,并将其放入Stack Context中 --> <s:bean name="lee.Person" id="p"> <s:param name="name" value="'yeeku'" /> <s:param name="age" value="29" /> </s:bean> <s:push value="#p"> <s:property value="name" /> <s:propery value="age" /> </s:push>
详细例子:
package com.struts; import com.entity.Users; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; /** * 控制器类 * 作用:处理用户的请求 * @author asus * */ public class PushAction extends ActionSupport { /** 成员变量:值栈中属性 */ private Users user; /** 重写execute方法 */ public String execute(){ user=new Users(); user.setName("固执的雨"); user.setAge(15); user.setSex("女"); //存入session会话范围 ActionContext.getContext().getSession().put("user", user); return SUCCESS; } /** JavaBean */ public Users getUser() { return user; } public void setUser(Users user) { this.user = user; } }
<%@ taglib uri="/struts-tags" prefix="s"%> <body> <!-- push标签 --> <h1>push标签</h1> <h4> 普通方式访问 </h4> 姓名: <s:property value="#session.user.name" /> 年龄: <s:property value="#session.user.age" /> 性别: <s:property value="#session.user.sex" /> <h4> 使用push标签后简化的访问方式 </h4> <s:push value="#session.user"> 姓名:<s:property value="name" /> 年龄:<s:property value="age" /> 性别:<s:property value="sex" /> </s:push> </body>
例子页面输出结果:
include标签
•include标签类似于JSP的<jsp:include>标签,用于包含一个Servlet或JSP页面。include标签的标签体内可以包含多个param标签,用于向被包含的页面传递请求参数。
属性如下:
例子:
<h2> 使用s:include标签来包含目标页面 </h2> <s:include value="include-file.jsp" /> <!--使用include标签来包含其他页面,并且传入参数--> <s:include value="include-file.jsp"> <s:param name="author" value="'yeeku'" /> </s:include> 被包含的页面仅使用表达式语言输出author参数,被包含页面的代码如下: <h3> 被包含的页面 </h3> <!--表达式语言输出author的请求参数--> ${param.author}
详细例子:
<body> <!-- include标签 --> <h4> 使用include标签包含(引用)jsp1.jsp </h4> <s:include value="jsp1.jsp" /> <h4> 使用include标签包含(引用)jsp2.jsp,使用嵌套的param标签向jsp2.jsp传递参数 </h4> <s:include value="jsp2.jsp"> <s:param name="name" value="'姓拼名命'" /> <s:param name="sex" value="'男'" /> </s:include> </body>
<body> 欢迎访问jsp1.jsp页面! </body>
<body> 欢迎访问jsp2.jsp页面! <br> <!--表达式语言输出author的请求参数,无法使用s:property标签取值,只能用EL表达式--> 姓名:${param.name } 性别:${param.sex } </body>
例子页面输出结果:
date标签
•date标签用于格式化输出日期值,也可用于输出当前日期值与指定日期值之间的时差
属性如下:
Ø注意:
Ø1、format属性用于指定日期的格式化样式,具体的样式规则可以参看java.text.SimpleDateFormat类的API文档。
Ø2、将nice属性设为true,可以输出指定日期值和当前日期值之间的时差,此时format属性失效,也就是说,当nice属性为true时,即使你指定了format属性,它也不会起作用
Ø3、如果没有使用nice属性,也没有指定format属性,那么date标签将会在国际化资源包中查找struts.date.format键,并以这个键的值作为日期的格式化样式;如果这个键
不存在,那么默认将会使用DateFormat.MEDIUM格式化样式。
Ø4、如果找不到name属性指定的Date对象,那么将返回空。
•第一步
•在ApplicationResources.properties文件中添加struts.date.format键
struts.date.format=yyyy/MM/dd hh:mm:ss
•第二步
•可以使用struts2的struts.custom.i18n.resources属性来设置默认的资源包,编辑struts.xml文件,使用constant元素来配置struts.custom.i18n.resources属性,
内容如下:
<constant name=“struts.custom.i18n.resources” value=“ApplicationResources”/>
•第三步
详细例子:
struts.date.format=yyyy/MM/dd hh:mm:ss
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <!-- 设置默认资源包 --> <constant name="struts.custom.i18n.resources" value="ApplicationResources"/> </struts>
<%@ page language="java" pageEncoding="UTF-8"%> <!-- 引入Struts2标签库 --> <%@ taglib uri="/struts-tags" prefix="s" %> <!-- 引入Canlendar的包 --> <%@page import="java.util.Calendar"%> <body> <% //获取当天指定点上的时间 Calendar calendar= Calendar.getInstance(); //通过calendar.set方法修改当前日期,将天数向后加10天 calendar.set(calendar.get(calendar.YEAR), calendar.get(calendar.MONTH), calendar.get(calendar.DATE) + 10); //存入application pageContext.setAttribute("futureDate",calendar.getTime()); %> <h1>date标签</h1> <h3>指定format="yyyy年MM月dd日"</h3> <s:date name="#attr.futureDate" format="yyyy年MM月dd日" /> <h3>没有使用format属性,指定nice="true",可以输出“获取到的日期值”和“现在的时间”之间的“时差”</h3> <!-- 将nice属性设为true,可以输出指定日期值和当前日期值之间的时差。 指定日期为:获取到的日期值。 当前日期为:今天,现在的时间。 --> <s:date name="#attr.futureDate" nice="true" /> <h3>没有使用format和nice属性,将以资源包中struts.date.format键的值作为格式化样式</h3> <s:date name="#attr.futureDate" /> </body>
例子页面输出结果:
datetimepicker日期控件
第一步:添加DOJO.jar包
第二步:
<!-- 引入Ajax标签 --> <%@ taglib uri="/struts-dojo-tags" prefix="sx"%> <head> <!-- 在JSP页面中加入head标签 负责在页面上导入Dojo所需要的CSS库和JavaScript库 --> <sx:head /> </head> <body> <!-- datetimepicker日期控件 日期月份会有乱码,具体解决网上百度吧~--> <sx:datetimepicker name="user.birthday" label="出生日期" value="%{'2008-9-20'}"/> </body>
结果页面:
if/elseif/else标签
•if/elseif标签属性test:为必填属性,是一个Boolean类型值,决定是否显示if标签内容。该标签标准格式如下:
<s:if test=“表达式”> …….. </s:if> <s:elseif test=“表达式”> …….. </s:elseif> <s:else> ……….. </s:else>
例子:
<!-- 引入Struts2标签库 --> <%@ taglib uri="/struts-tags" prefix="s"%> <body> <!-- OGNL是通常要结合Struts 2的标志一起使用。struts2标签里不能使用EL表达式。 --> <h4> 例子1 </h4> <!-- 定义一个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> </body>
iterator(迭代标签)
•描述:用于遍历集合(java.util.Collection)List,Map,数组或枚举值(java.util.iterator)。
该标签的属性如下表:
•int getCount():返回当前迭代过元素的总数。
•int getIndex():返回当前迭代元素的索引。
•boolean isEven():判断当前迭元素是否为偶数。
•boolean isOdd():判断当前迭元素是否为奇数。
•boolean isFirst():判断当前迭元素是否为第一个元素。
•boolean isLast():判断当前迭元素是否为最后一个元素
例子:
<!-- 引入Struts2标签库 --> <%@ taglib uri="/struts-tags" prefix="s" %> <body> <!-- iterator迭代标签 --> <h1>iterator迭代标签</h1> <h4>迭代List,不使用status</h4> <s:iterator value="{'zhangsan' , 'lisi' , 'wangwu'}" > <s:property/><br> </s:iterator> <h4>迭代List,使用status</h4> <table border="1" > <tr> <th>当前元素</th> <th>当前迭代的元素的总数</th> <th>当前迭代的元素的索引</th> <th>判断当前迭代的元素是否是偶数</th> <th>判断当前迭代的元素是否是奇数</th> <th>判断当前迭代的元素是否是第一个元素</th> <th>判断当前迭代的元素是否是最后一个元素</th> </tr> <s:iterator value="{'zhangsan' , 'lisi' , 'wangwu'}" status="status" > <tr> <td><s:property/></td> <td><s:property value="#status.getCount()" /></td> <td><s:property value="#status.index" /></td><!-- 简写方式:index 不简写方式:getIndex() --> <td><s:property value="#status.isEven()" /></td> <td><s:property value="#status.odd" /></td><!-- 简写方式:odd 不简写方式:isOdd() --> <td><s:property value="#status.first" /></td> <td><s:property value="#status.last" /></td> </tr> </s:iterator> </table> <h4>迭代Map,不使用status属性, #{}是用来构造Map的写法</h4> <s:iterator value="#{'first':'zhangsan', 'second':'lisi', 'third':'wangwu' }" > <s:property value="key" /> = <s:property value="value" /><br> </s:iterator> </body>
结果页面:
token标签(实现防止表单重复提交)
由于某些原因,用户在进行类似表单提交的操作后,以为表单未被提交,会进行多次的重复提交。为了避免用户多次提交给服务器带来负荷。我们会对表单提交这样的操作进行一些处理,以告诉用户不要重复提交。
第一步:使用<s:token></s:token>标签:
登录页面中的关键技术就是使用了标签库中的<s:token></s:token>标签,
它的作用就是在用户访问此页面时会生成一个sessionId,
在提交时会服务器会据此验证表单是否已提交,
提交到的Action便能配置TokenInterceptor拦截器验证表单是否重复提交。
第二步:配置XML文件
<result name="success">/success.jsp</result>
<result name="invalid.token">/error.jsp</result>
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
此Action下,我们配置了token拦截器,另注意到在此Action下我们还配置了一个 “invalid.token”result,提交时服务器如果根据token标签产生的sessionId判断出表单已提交,
它则返回invalid.token指向的视图。比如这里,如果重复提交则会转到.../error.jsp中去。
另不要忘记了引入默认的拦截器栈。
<s:token />标签防止重复提交,用法如下:
第一步:在表单中加入<s:token />
<s:form action="helloworld_other" method="post" namespace="/test">
<s:textfield name="person.name"/>
<s:token/>
<s:submit/>
</s:form>
第二步:
<action name="helloworld_*" class="com.action.HelloWorldAction" method="{1}">
<result>ok.jsp</result>
<result name="invalid.token">error.jsp</result>
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
详细例子(用户登录):
package com.entity; import java.util.Date; /** * 用户类 * @author asus * */ public class Users { /** 属性 */ private String name; private String password; private int age; private String sex; private Date birthday; /** 构造方法 */ public Users() { super(); } public Users(String name, String password) { super(); this.name = name; this.password = password; } /** javaBean */ public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
<%@ taglib uri="/struts-tags" prefix="s" %> <body> <!-- Struts2 表单标签 --> <!-- action=loginAction 为token拦截器,重复提交,跳转错误页面 action=login2Action 为tokenSession拦截器,重复提交时,留着当前页面,且拦截本次提交 --> <s:form action="loginAction" method="post" theme="simple" > <!-- 加入token标签 --> <s:token/> 用户名:<s:textfield name="user.name" /> 密码: <s:password name="user.password" /> <s:submit value="登录按钮" /> </s:form> </body>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="struts2" extends="struts-default"> <!-- token标签 1-配置token拦截器,会实现若表单重复提交则跳转错误页面。 --> <action name="loginAction" class="com.struts.LoginAction" > <result>/s_token/success.jsp</result> <!-- 当判断表单重复提交时,token拦截器则会返回invalid.token指向的视图 --> <result name="invalid.token" >/s_token/error.jsp</result> <!-- 配置防止表单重复提交的局部拦截器 Struts2自带的拦截器,当然也可以配置成全局默认的,看需求。 注意:不要忘记了引入默认的拦截器栈 --> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> <!-- token标签 2-配置tokenSession拦截器,会实现若表单重复提交时不会跳转页面(留在当前页面)且拦截本次提交。 --> <action name="login2Action" class="com.struts.LoginAction" > <result>/s_token/success.jsp</result> <!-- 配置防止表单重复提交的局部拦截器 Struts2自带的拦截器,当然也可以配置成全局默认的,看需求。 注意:不要忘记了引入默认的拦截器栈--> <interceptor-ref name="tokenSession"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package> </struts>
package com.struts; import com.entity.Users; import com.opensymphony.xwork2.ActionSupport; /** * 控制器类 * 作用:处理用户的请求 * @author asus * */ public class LoginAction extends ActionSupport { /** 成员变量:值栈中属性 */ private Users user; /** 重写execute方法 */ public String execute(){ System.out.println("请求Action进入execute()方法。。");//控制台测试,是否多次重复提交。 //验证登录 if(user!=null){ if(user.getName().equals("admin") && user.getPassword().equals("a123")){ return SUCCESS; } } return SUCCESS;//只为掩饰效果,密码错误也会走成功页面 } /** JavaBean */ public Users getUser() { return user; } public void setUser(Users user) { this.user = user; } }
<body> 登陆成功进入此页面! </body>
<body> 当表单重复提交时跳转到此页面! </body>
结果页面: