Struts2 把全部標籤都定義在URI爲/struts-tags的命名空間下。能夠分爲3類:UI標籤(主要用於生成HTML元素的標籤,可分爲表單標籤和非表單標籤)、非UI標籤(主要用於數據訪問和邏輯控制等,分爲數據標籤和控制標籤)和Ajax標籤(主要用於Ajax支持的標籤)。html
OGNL(Object Graphic Navigation Language,對象圖導航語言),是個開源項目。OGNL是一種功能強大的EL(Expression Language,表達式語言),能夠通過簡單的表達式來訪問Java對象中的屬性。java
OGNL首先在WebWork項目中獲得應用,OGNL是Struts2框架視圖默認的表達式語言,OGNL表達式是Struts 2框架的特色之一。node
標準的OGNL會設定一個根對象(root對象)。假設使用標準OGNL表達式來求值(不是Struts 2 OGNL),若是OGNL上下文有兩個對象,foo對象和bar對象,同時foo對象被設置爲根對象(root),則利用下面的OGNL表達式求值。web
#foo.blah // 返回foo.getBlah() #bar.blah // 返回bar.getBlah() blah // 返回foo.getBlah(),由於foo爲根對象
若是要訪問的不是根對象,須要使用命名空間,用「#」表示。若是是根對象,則不用指定。
ajax
在Struts 2框架中,值棧(Value Stack)就是OGNL的根對象。假設值棧中存在兩個對象實例Man和Animal,這兩個對象實例都有一個name屬性,Animal有一個species屬性,Man有一個salary屬性。假設Animal在值棧的頂部,Man在Animal後面,如圖所示。session
一個包含了Animal和Man的值棧app
下面的代碼片斷能更好地理解OGNL表達式。框架
species // 調用animal.getSpecies() salary // 調用man.getSalary() name // 調用animal.getName(),由於Animal位於值棧的頂部
最後一行實例代碼返回的是animal.getName()返回值,即返回了Animal的name屬性,由於Animal是值棧的頂部元素,OGNL將從頂部元素搜索,因此會返回Animal的name屬性值。若是要得到Man的name值,則須要以下代碼:
jsp
man.name
Struts 2容許在值棧中使用索引,實例代碼以下:post
[0].name // 調用animal.getName() [1].name // 調用man.getName()
Struts 2中的OGNL Context是ActionContext,如圖所示。
Struts 2的OGNL Context結構示意圖
因爲值棧是Struts 2中OGNL的根對象。若是用戶須要訪問值棧中的對象,則能夠經過以下代碼訪問值棧中的屬性:
${foo} // 得到值棧中的foo屬性
若是訪問其餘Context中的對象,因爲不是根對象,在訪問時須要加#前綴。
application對象:用來訪問ServletContext,如#application.userName或者#application ["userName"],至關於調用Servlet的getAttribute("userName")。
session對象:用來訪問HttpSession,如#session.userName或者#session["userName"],至關於調用session.getAttribute("userName")。
request對象:用來訪問HttpServletRequest屬性的Map,如#request.userName或者#request["userName"],至關於調用request.getAttribute("userName")。如在3.2.1節中StrutsAction類中代碼:
Map request=(Map)ActionContext.getContext().get("request"); request.put("name",getName());
這就是先獲得request對象,而後把值放進去,在該例的success.jsp中有:
<s:property value="#request.name"/>
其中#request.name至關於調用了request.getAttribute("name")。
使用以下代碼直接生成一個List對象:
{e1, e2, e3…}
下面的代碼能夠直接生成一個Map對象:
#{key: value1, key2: value2, …}
對於集合類型,OGNL表達式可使用in和not in兩個元素符號。其中,in表達式用來判斷某個元素是否在指定的集合對象中;not in判斷某個元素是否不在指定的集合對象中,代碼以下所示:
<s: if test="'foo' in {'foo', 'bar'}"> … </s: if>
或
<s: if test="'foo' not in {'foo', 'bar'}"> … </s: if>
除了in和not in以外,OGNL還容許使用某個規則得到集合對象的子集,經常使用的有如下3個相關操做符。
?:得到全部符合邏輯的元素。
^:得到符合邏輯的第一個元素。
$:得到符合邏輯的最後一個元素。
以下面的代碼:
Person.relatives.{?# this.gender=='male'}
該代碼能夠得到Person的全部性別爲male的relatives集合。
數據標籤屬於非UI標籤,主要用於提供各類數據訪問相關的功能,數據標籤主要包括如下幾個。
property:用於輸出某個值。
set:用於設置一個新變量。
param:用於設置參數,一般用於bean標籤和action標籤的子標籤。
bean:用於建立一個JavaBean實例。
action:用於在JSP頁面直接調用一個Action。
date:用於格式化輸出一個日期。
debug:用於在頁面上生成一個調試連接,當單擊該連接時,能夠看到當前值棧和Stack Context中的內容。
il8n:用於指定國際化資源文件的baseName。
include:用於在JSP頁面中包含其餘的JSP或Servlet資源。
push:用於將某個值放入值棧的棧頂。
text:用於輸出國際化(國際化內容會在後面講解)。
url:用於生成一個URL地址。
property標籤的做用是輸出指定值。property標籤輸出value屬性指定的值。若是沒有指定的value屬性,則默認輸出值棧棧頂的值。該標籤有以下幾個屬性:
default:該屬性是可選的,若是須要輸出的屬性值爲null,則顯示default屬性指定的值。
escape:該屬性是可選的,指定是否escape HTML代碼。
value:該屬性是可選的,指定須要輸出的屬性值,若是沒有指定該屬性,則默認輸出值棧棧頂的值。該屬性也是最經常使用的,如前面用到的:
<s:property value="#request.name"/>
id:該屬性是可選的,指定該元素的標誌。
對值棧中的表達式進行求值,並將結果賦給特定做用域中的某個變量名。該標籤有以下幾個屬性:
name:該屬性是必選的,從新生成新變量的名字。
scope:該屬性是可選的,指定新變量的存放範圍。通常爲application、session、request、page和action。若是沒有指定該屬性,則默認放置在值棧中。
value:該屬性是可選的,指定賦給新變量的值。若是沒有指定該屬性,則將值棧棧頂的值賦給新變量。
id:該屬性是可選的,指定該元素的引用id。
下面是一個簡單例子,展現了property標籤訪問存儲於session中的user對象的多個字段:
<s:property value="#session['user'].username"/> <s:property value="#session['user'].age"/> <s:property value="#session['user'].address"/>
因爲每次都要重複使用#session['user'],不只煩人還容易引起錯誤,更好的作法是定義一個臨時變量,使用set標籤使得代碼易於閱讀:
<s:set name="user" value="#session['user'] " /> <s:property value="#user.username"/> <s:property value="#user.age" /> <s:property value="#user.address" />
param標籤主要用於爲其餘標籤提供參數,該標籤有以下幾個屬性:
name:該屬性是可選的,指定須要設置參數的參數名。
value:該屬性是可選的,指定須要設置參數的參數值。
id:該屬性是可選的,指定引用該元素的id。
例如,要爲name爲fruit的參數賦值:
<s:param name= "fruit">apple</s:param>
或者
<s:param name="fruit" value="apple" />
指定一個名爲fruit的參數,該參數的值爲apple對象的值,若是該對象不存在,則fruit的值爲null。
若是想指定fruit參數的值爲apple字符串,則應該這樣寫:
<s:param name="fruit" value="'apple'" />
用於建立一個JavaBean實例。建立JavaBean實例時,能夠在該標籤內使用param標籤爲該JavaBean實例傳入屬性。若是要使用param標籤傳入屬性值,則應該爲該JavaBean類提供setter方法。若是還但願訪問該屬性值,則必須爲該屬性提供getter方法。該標籤有以下幾個屬性:
name:該屬性是必選的,用來指定要實例化的JavaBean的實現類。
id:該屬性是可選的,若是指定了該屬性,則該JavaBean實例會被放入Stack Context中,從而容許直接經過id屬性來訪問該JavaBean實例。下面是一個簡單的例子:
有一個Student類,該類中有name屬性,並有其getter和setter方法:
public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name=name; } }
而後在JSP文件的body體中加入下面的代碼:
<s:bean name="Student"> <s:param name="name" value="'zhangsan'"/> <s:property value="name"/> </s:bean>
在項目中導入Struts 2的Jar包,再把Student類放在項目的src文件夾下(若是Student類在在某個包下面,那麼<s:bean>標籤的name要加上包名。例如org.bean.Student),<s:bean>標籤內容放在一個JSP文件的body體內,再修改web.xml文件,就能夠部署運行該項目,會獲得如圖所示的界面。
bean標籤實例界面
也能夠把bean標籤的內容改成:
<s:bean name="Student" id="s" > <s:param name="name" value="'zhangsan'"/> </s:bean> <s:property value="#s.name"/>
使用action標籤能夠容許在JSP頁面中直接調用Action。該標籤有如下幾個屬性:
id:該屬性是可選的,該屬性將會做爲該Action的引用標誌id。
name:該屬性是必選的,指定該標籤調用哪一個Action。
namespace:該屬性是可選的,指定該標籤調用的Action所在的namespace。
executeResult:該屬性是可選的,指定是否要將Action的處理結果頁面包含到本頁面。若是值爲true,就是包含,false就是不包含,默認爲false。
ignoreContextParam:該屬性是可選的,指定該頁面中的請求參數是否須要傳入調用的Action。若是值爲false,將本頁面的請求參數傳入被調用的Action。如爲true,不將本頁面的請求參數傳入到被調用的Action。
date標籤主要用於格式化輸出一個日期。該標籤有以下屬性:
format:該屬性是可選的,若是指定了該屬性,將根據該屬性指定的格式來格式化日期。
nice:該屬性是可選的,該屬性的取值只能是true或false,用於指定是否輸出指定日期和當前時刻之間的時差。默認爲false,即不輸出時差。
name:屬性是必選的,指定要格式化的日期值。
id:屬性是可選的,指定引用該元素的id值。
nice屬性爲true時,通常不指定format屬性。由於nice爲true時,會輸出當前時刻與指定日期的時差,不會輸出指定日期。當沒有指定format,也沒有指定nice="true"時,系統會到國際化資源文件中尋找key爲struts.date.format的消息,將該消息當成格式化文原本格式化指定日期,若是沒法找到,則默認採用DateFormat.MEDIUM格式輸出。其用法爲:
<s:date name="指定日期取值" format="日期格式"/><!-- 按指定日期格式輸出 --> <s:date name="指定日期取值" nice="true"/><!-- 輸出時間差 --> <s:date name="指定日期取值"/><!—默認格式輸出-->
例子:
java
import java.util.Date; public class Student { private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
jsp
<s:bean name="Student"> <s:param name="birthday" value="'2011-12-10'"/> <s:date name="birthday" /><br/> <s:date name="birthday" format="yyyy-MM-dd hh:mm:ss"/><br/> <s:date name="birthday" nice="true"/><br/> </s:bean>
include標籤用於將一個JSP頁面或一個Servlet包含到本頁面中。該標籤有以下屬性:
value:該屬性是必選的,指定須要被包含的JSP頁面或Servlet。
id:該屬性是可選的,指定該標籤的id引用。
用法以下:
<s:include value="JSP或Servlet文件" id="自定義名稱"/>
屬於非UI標籤,主要用於完成流程的控制,以及對值棧的控制。控制標籤有如下幾個:
if:用於控制選擇輸出的標籤。
elseif:用於控制選擇輸出的標籤,必須和if標籤結合使用。
else:用戶控制選擇輸出的標籤,必須和if標籤結合使用。
append:用於將多個集合拼接成一個新的集合。
generator:用於將一個字符串按指定的分隔符分隔成多個字符串,臨時生成的多個子字符串可使用iterator標籤來迭代輸出。
iterator:用於將集合迭代輸出。
merge:用於將多個集合拼接成一個新的集合,但與append的拼接方式不一樣。
sort:用於對集合進行排序。
subset:用於截取集合的部分元素,造成新的子集合。
這3個標籤能夠組合使用,但只有if標籤能夠單獨使用,而elseif和else標籤必須與if標籤結合使用。if標籤能夠與多個elseif標籤結合使用,但只能與一個else標籤使用。其用法格式以下:
<s:if test="表達式"> 標籤體 </s:if> <s:elseif test="表達式"> 標籤體 </s:elseif> <!--容許出現屢次elseif標籤--> ... <s:else> 標籤體 </s:else>
該標籤主要用於對集合進行迭代,這裏的集合包含List、Set,也能夠對Map類型的對象進行迭代輸出。該標籤的屬性以下:
value:該屬性是可選的,指定被迭代的集合,被迭代的集合一般都由OGNL表達式指定。若是沒有指定該屬性,則使用值棧棧頂的集合。
id:該屬性是可選的,指定集合元素的id。
status:該屬性是可選的,指定迭代時的IteratorStatus實例,經過該實例可判斷當前迭代元素的屬性。若是指定該屬性,其實例包含以下幾個方法:
int getCount():返回當前迭代了幾個元素。
int getIndex():返回當前被迭代元素的索引。
boolean isEven:返回當前被迭代元素的索引元素是不是偶數。
boolean isOdd:返回當前被迭代元素的索引元素是否是奇數。
boolean isFirst:返回當前被迭代元素是不是第一個元素。
boolean isLast:返回當前被迭代元素是不是最後一個元素。
應用舉例:
<%@ page language="java" pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <html> <head> <title>控制標籤</title> </head> <body> <table border="1" width="200"> <s:iterator value="{'apple','orange','pear','banana'}"id="fruit" status="st"> <tr <s:if test="#st.even">style="background-color:silver"</s:if>> <td><s:property value="fruit"/></td> </tr> </s:iterator> </table> </body> </html>
經過添加Struts 2必須的Jar包,再創建上面JSP文件,修改web.xml後,就能夠部署運行,運行結果如圖所示。
iterator標籤實例運行結果
用於將多個集合對象拼接起來,組成一個新的集合。必須指定一個id屬性,該屬性肯定拼接的新集合的名稱。該標籤經過param標籤來指定每個集合,而後把這些集合拼接起來。
應用舉例,能夠把上例的JSP文件進行修改,其代碼爲:
<%@ page language="java" pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>控制標籤</title> </head> <body> <s:append id="newList"> <s:param value="{'apple','orange','pear','banana'}"></s:param> <s:param value="{'chinese','english','french'}"></s:param> </s:append> <table border="1" width="200"> <s:iterator value="#newList" id="fruit" status="st"> <tr <s:if test="#st.even">style="background-color:silver"</s:if>> <td> <s:property value="fruit" /> </td> </tr> </s:iterator> </table> </body> </html>
部署運行,運行結果如圖所示。
append標籤實例運行界面
與append標籤的區別,只是拼接方式不一樣。
假設有2個集合,第一個集合包含3個元素,第二個集合包含2個元素,分別用append標籤和merge標籤方式進行拼接,它們產生新集合的方式有所區別。下面分別列出:
用append方式拼接,新集合元素順序爲:
第1個集合中的第1個元素
第1個集合中的第2個元素
第1個集合中的第3個元素
第2個集合中的第1個元素
第2個集合中的第2個元素
用merge方式拼接,新集合元素順序爲:
第1個集合中的第1個元素
第2個集合中的第1個元素
第1個集合中的第2個元素
第2個集合中的第2個元素
第1個集合中的第3個元素
代碼以下:
<%@ page language="java" pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>控制標籤</title> </head> <body> <s:merge id="newList2"> <s:param value="{'apple','orange','pear','banana'}"></s:param> <s:param value="{'chinese','english','french'}"></s:param> </s:merge> <table border="1" width="200"> <s:iterator value="#newList2" id="fruit2" status="st2"> <tr <s:if test="#st2.even">style="background-color:silver"</s:if>> <td> <s:property value="fruit2" /> </td> </tr> </s:iterator> </table> </body> </html>
大部分的表單標籤和HTML表單元素是一一對應的關係,以下面的代碼片斷:
<s:form action="login.action" method="post"/>
對應着:
<form action="login.action" method="post"/>
<s:textfield name="username" label="用戶名" />
對應着:
用戶名:<input type="text" name="username">
<s:password name="password" label="密碼"/>
對應着:
密碼:<input type="password" name="pwd">
還有下面這種狀況,若是有這樣一個JavaBean類,類名爲「User」,該類中有兩個屬性:一個是username;另外一個是password,並分別生成它們的getter和setter方法,在JSP頁面的表單中能夠這樣爲表單元素命名:
<s:textfield name="user.username" label="用戶名" /> <s:password name="user.password" label="密碼"/>
下面介紹和HTML標籤元素不是一一對應的幾個重要的表單標籤:
建立多個複選框。該標籤須要指定一個list屬性。用法舉例:
<s:checkboxlist label="請選擇你喜歡的水果" list="{'apple','oranger','pear','banana'}" name="fruit"> </s:checkboxlist>
或者爲:
<s:checkboxlist label="請選擇你喜歡的水果" list="#{1:'apple',2:'oranger',3:'pear',4:'banana'}" name="fruit"> </s:checkboxlist>
這兩種方式的區別:前一種根據name取值時取的是選中字符串的值;後一種在頁面上顯示的是value的值,而根據name取值時取的倒是對應的key,這裏就是一、二、3或4。
combobox標籤生成一個單行文本框和下拉列表框的組合。兩個表單元素只能對應一個請求參數,只有單行文本框裏的值才包含請求參數,下拉列表框只是用於輔助輸入,並無name屬性,故不會產生請求參數。用法舉例:
<s:combobox label="請選擇你喜歡的水果" list="{'apple','oranger','pear','banana'}" name="fruit"> </s:combobox>
datetimepicker標籤用於生成一個日期、時間下拉列表框。當使用該日期、時間列表框選擇某個日期、時間時,系統會自動將選中日期、時間輸出指定文本框中。用法舉例:
<s:form action="" method=""> <s:datetimepicker name="date" label="請選擇日期"></s:datetimepicker> </s:form>
注意:在使用該標籤時,要在HTML的head部分加入<s:head/>。
select標籤用於生成一個下拉列表框,經過爲該元素指定list屬性的值,來生成下拉列表框的選項。用法舉例:
<s:select list="{'apple','oranger','pear','banana'}" label="請選擇你喜歡的水果"></s:select>
或者爲:
<s:select list="fruit" list="#{1:'apple',2:'oranger',3:'pear',4:'banana'}" listKey="key"listValue="value"></s:select>
radio標籤的用法與checkboxlist用法很類似,惟一的區別就是checkboxlist生成的是複選框,而radio生成的是單選框。用法舉例:
<s:radio label="性別" list="{'男','女'}" name="sex"></s:radio>
或者爲:
<s:radio label="性別" list="#{1:'男',0:'女'}" name="sex"> </s:radio>
head標籤主要用於生成HTML頁面的head部分。在介紹<s:datetimepicker>標籤時說過,要在head中加入該標籤,主要緣由是<s:datetimepicker>標籤中有一個日曆小控件,其中包含了JavaScript代碼,因此要在head部分加入該標籤。
若是須要在頁面中使用Ajax組件,就須要在head標籤中加入theme="ajax"屬性。
非表單標籤主要用於在頁面中生成一些非表單的可視化元素。這些標籤不常常用到,下面大體介紹一下這些標籤:
a:生成超連接。
actionerror:輸出Action實例的getActionMessage()方法返回的消息。
component:生成一個自定義組件。
div:生成一個div片斷。
fielderror:輸出表單域的類型轉換錯誤、校驗錯誤提示。
tablePanel:生成HTML頁面的Tab頁。
tree:生成一個樹形結構。
treenode:生成樹形結構的節點。