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>
結果頁面: