-
-
-
- Struts 2标簽簡介
- Struts 标簽分類
- 使用Struts标簽庫
- OGNL
- OGNL集合運算
- OGNL表達式對靜态屬性的通路
- 控制标簽
- if/else if/else
- iterator
- generator
- merge
- subset
- 資料标簽
- Action
- Bean
- Date
- debug
- include
- param
- push
- Set
- url
- property
- Struts 2的模闆和主題
- 設定主題方式
- Struts 2 元素屬性
- JavaScript 擁有屬性
- 滑鼠懸停的通用屬性
- css設定屬性
- 表單元素的name于value屬性
- 表單元素
- updownselect
- 非表單标簽
- component
-
-
Struts 2标簽簡介
與Struts1标簽庫相比,Struts 2 的标簽庫有一個巨大的改進之處: Struts2 标簽庫的标簽不依賴于任何表現層技術,也就是說,Struts2 提供的大部分标簽,可以在各種表現層技術中使用,包括最常用的JSP 頁面,也可以在Velocity 和FreeMarker 等模闆技術中使用。
雖然Struts 2 大部分标簽可以在所有表現層技術中使用,但也有極少數标簽在某些表現層技術中使用時會受到限制,這一點請開發者務必要注意。
Struts 标簽分類
雖然Struts2 把所有的标簽都定義在URI 為“/struts-tags”的空間下,但我們依然可以對Struts2 标簽進行簡單的分類。
Struts2 可以将所有标簽分成如下三類:
- UI (User Interface,使用者界面) 标簽: 主要用于生成HTML 元素的标簽。
- 非UI 标簽: 主要用于資料通路、邏輯控制等的标簽。
- Ajax 标簽: 用于Ajax (Asynchronous JavaScript And XML) 支援的标簽。
- 表單标簽: 主要用于生成HTML 頁面的form 元素,以及普通表單元素的标簽。
- 非表單标簽: 主要用于生成頁面上的樹、Tab 頁等标簽。
- 流程控制标簽: 主要包含用于實作分支、循環等流程控制的标簽。
- 資料通路标簽: 主要包含用于輸出ValueStack 中的值、完成國際化等功能的标簽。
使用Struts标簽庫
在使用的時候,還是需要添加這一指令。
在上面标簽中,因為該标簽以“s”作為字首,故該标簽需要使用URI 為/struts-tags 的标簽庫處理,通過字首關聯,系統知道從Struts 2 标簽庫中尋找名為abc 的标簽來處理相應标簽。
OGNL
OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,他是一個開源項目。Struts架構使用OGNL作為預設的表達式語言。
在Struts2 應用中,視圖頁面可通過标簽直接通路Action 屬性值( 實際上這隻是一種假想,類似于Web 應用application.session.request和page 四個範圍的“銀行”一樣,Struts2 自行維護一個特定範圍的“銀行”, Action 将資料放入其中,而JSP 頁面可從其中取出資料,表面上似乎JSP 可直接通路Action 資料),當Action屬性不是簡單值(基本類型值或String類型值) 時,而是某個對象,甚至是數組、集合時,就需要使用表達式語言來通路這些對象、數組、集合的内部資料了, Struts 2 利用OGNL 表達式語言來實作這個功能。
在傳統的OGNL 表達式求值中,系統會假設隻有一個“根”對象。下面是标準OGNL 表達值,如果系統的StackContext 中包含兩個對象: foo 對象,它在Context 中的名字為foo; bar對象,在Context 中的名字為bar,并将foo 對象設定成Context 的根對象。
//傳回foo.getBlah () 方法的傳回值,屬性一般都有set、get方法。
#foo.blah
//傳回bar.getBlah() 方法的傳回值
#bar.blah
//因為foo 是根對象,是以預設是取得foo對象的blah屬性
blan
如果需要通路的屬性屬于根對象,則可以直接通路該屬性,如blah; 否則必須使用一個對象名作為字首修飾該屬性,如#bar.blah。
Struts 2 使用标準的Context 來進行OGNL 表達式語言求值,OGNL 的頂級對象是一個Context,這個Context 對象就是一個Map 類型執行個體,根對象有是ValueStack對象。
存放在ValueStack裡面可以通過${屬性名}(el表達式),直接擷取。
值棧的簡單定義:
- 簡單的說,值棧是對應每一個請求對象的輕量級的資料存儲中心,在這裡統一管理着資料,供Action、Result、Interceptor等Struts2的其他部分使用,這樣資料被集中管理起來而不淩亂。
- 當有請求的時候,Struts2會為每個請求建立一個新的值棧,也就是說,值棧和請求是一一對應的,不同的請求,值棧也不一樣, 而值棧封裝了一次請求所有需要操作的相關的資料。
- 正是因為值棧和請求的對應關系,是以值棧能保證線程安全的為每個請求提供公共的資料存取服務。
- 就是ROOT根對象,ognl通路值棧不用加任何的通路字首,隻需action中聲明相應的屬性,并且生成屬性對應的set和get方法,頁面中通過struts2标簽就可以存放/取出值棧中的值,EL表達式${username}如果沒有加通路範圍,通路的也是值棧,這隻是最簡單的值棧應用
- 值棧的特點:如果通路的值棧裡有多個對象,且相同的屬性在多個對象中同時出現,則值棧會按照從棧頂到棧底的順序,尋找第一個比對的對象。
參考學習:這裡寫連結内容
- parameters 對象:用于通路HTTP 請求參數。例如#parameters[‘foo]或#parameters.foo,用于傳回調用HttpServletRequest的getParameter(“foo”)方法的傳回值。
- request 對象:用于通路HttpServletRequest 的屬性。例如#request [foo]或#request.foo,用于傳回調用HttpServletRequest的getAttribute(“foo”)方法的傳回值。
- session 對象:用于通路HttpSession的屬性。例如#session[‘foo’]或#session.foo,用于傳回調用HttpSession的getAttribute(“foo”)方法的傳回值。
- application 對象:用于通路ServletContext的屬性。例如#application[foo]或#application.foo,用于傳回調ServletContext的getAtribute(“foo”) 方法的傳回值。
- attr對象:該對象将依次搜尋如下對象;PageContext.HttpServletRequest、HttpSession、ServletContext中的屬性。
注意:OGNL 的Stack Context 是整個OGNL 計算、求值的Context,而ValueStack 隻是StackContex 内的“根”對象而已。OGNL 的Stack Context裡除了包括ValueStack 這個根之外,還包括parameters.request.session.application.attr 等命名對象,但這些命名對象都不是根。Stack Context “根”對象和普通命名對象的差別在于:
- 通路Stack Context 裡的命名對象需要在對象名之前添加# 字首;
- 當通路OGNL 的Stack Context 裡“根”對象的屬性時,可以省略對象名。
OGNL集合運算
建立List類型集合的文法:
建立Map類型集合的文法:
多個元素之間用英文隔開。
對于集合,OGNL 提供了兩個運算符: in 和notin,其中in 判斷某個兀素是含在指定集合中; not in 則用于判斷某個元素是否不在指定集合中。
除此之外,OGNL 還允許通過某個規則取得集合的子集。取得子集時有如下三個操作符:
- ? 取出所有符合選擇邏輯的元素。
- ^取出符合選擇邏輯的第一個元素。
- $: 取出符合選擇邏輯的最後一個元素。
person.relatives.{? #this.gender== ‘male’} ,直接在集合後緊跟.{ }運算符表明用于取出該集合的子集,在{ }内使用?表明取出所有符合選擇邏輯的元素,而#this 代表集合裡元素。是以,上面代碼的含義是: 取出person 的所有性别為male 的relatives (親戚) 集合。
OGNL表達式對靜态屬性的通路
為了讓OGNL對靜态屬性的設定,需要在Struts.xml中進行設定。
OGNL 表達式可以通過如下文法來通路靜态成員:
<constant name="struts.oqn1.allowStatiaMethodAccess" value="true"></constant>
@classNameQstaticField
@className@staticMethod(val...)
控制标簽
- if: 用于控制選擇輸出的标簽。
- elself/elseif: 與if 标簽結合使用,用于控制選擇輸出的标簽。else: 與if 标簽結合使用,用于控制選擇輸出的标簽。
- append: 用于将多個集合拼接成一個新的集合。
- generator:它是一個字元串解析器,用于将一個字元串解析成一個集合。iterator: 這是一個疊代器,用于将集合疊代輸出。
- merge: 用于将多個集合拼接成一個新的集合。但與append 的拼接方式有所不同。sort: 這個标簽用于對集合進行排序。
- subset: 這個标簽用于截取集合的部分元素,形成新的子集合。
if/else if/else
這三個标簽可以組合使用,隻有<…>标簽可以單獨使用,後面的
<s:set value="90" var="age"/>
<s:if test="#age>60">老年人</s:if>//test是對條件
<s:elseif test="#age>35">中年人</s:elseif>
<s:else>年輕人</s:else>
<s:debug></s:debug>
我們通過可以看到它把該屬性添加到Stack Context中了。
iterator
iterator 标簽主要用于對集合進行疊代,這裡的集合包含List、Set 和數組,也可對Map 集合進行疊代輸出。使用
<table border="2px">
<s:iterator value="{'laoqiang','laoqiangtest','laoqiangtest1'}" var="name" status="st">//value構造的集合是通過OGNL來建立,var是給疊代器起的名字,友善你去引用。
<tr <s:if test="#st.odd">style="background-color:#bbbbbb"</s:if>>//通過設定疊代的的索引奇數,來設定行的背景顔色。
<td>
<s:property value="#st.count"/>
<s:property value="name"></s:property>
</td>
</tr>
</s:iterator>
</table>
<s:append var="newlist1">
<s:param value="#{'name':'laoqiang','age':'12','sex':'man'}"></s:param>
<s:param value="#{'test1','test3','test2'}"></s:param>
</s:append>
<table>
<s:iterator value="#newlist1" status="sttt1" var ="new2">
<tr>
<td>
<s:property value="key"></s:property></td>
<td>
<s:property value="value"/>
</td>
</tr>
</s:iterator>
</table>
在該例子中,我們展示了在對map集合的合并,與周遊顯示,同時我們還需要知道,在map中,如果沒有value,隻有key,那麼顯示的時候,就按照key顯示。
generator
使用generator标簽可以将指定字元串按指定分隔符分隔成多個子串,臨時生成的多個子串可以使用iterator 标簽來疊代輸出。可以這樣了解: generator将一個字元串轉化成一個Iterator 集合。在該标簽的标簽體内,整個臨時生成的集合将位于ValueStack 的頂端,但一旦該标簽結束,該集合将被移出ValueStack。
- count : 該屬性是一個可選的屬性,該屬性指定生成集合中元素的總數。
- separator: 這是一個必填的屬性,該屬性指定用于解析字元串的分隔符。
- val: 這是一個必填的屬性,該屬性指定被解析的字元串。
- converter: 這是一個可選的屬性,該屬性指定一個轉換器,該轉換器負責将集合中的每個字元串轉換成對象,通過該轉換器可以将一個字元串解析成對象集合。該屬性值必須是一個org.apache.Struts.util.lteratorGenerator.over 對象。
- var: 這是 一個可選的屬性,如果指定了該屬性,則将生成的Iterator 對象放入StackContext中。該屬性也可替換成id,但推薦使用var 屬性。
<s:generator separator="," val="'laoqiang,laoqiange,laoqiangt'" var="books">
<s:debug></s:debug>
<table border="1px">
<s:iterator>
<tr>
<td>
<s:property></s:property>
</td>
</tr>
</s:iterator>
</table>
</s:generator>
${requestScope.books}
如果指定了var 屬性,就可将生成的集合放入Struts 2 的Stack Context 中(實際上還會設定成request 範圍的屬性)。
Struts2 的很多标簽都與該标簽類似,它們都可以指定var (以前是id )屬性,一旦指定了var 屬性,則會将新生成、新設定的值放入Stack Context 中(必須通過#name 形式通路); 如果不指定var屬性, 則新生成、新設定的值不會放入Stack Context 中, 是以隻能在該标簽内部通路新生成、新設定的值一一此時新生成、新設定的值位于ValueStack中, 是以可以直接通路。
merge
該标簽和append一樣的功能,都是将多個集合合并成一個集合,但是差別就在于添加的順序不同。
<s:merge var="list" >
<s:param value="{'laoqiang','laoqiang1','laoqiang2'}"></s:param>
<s:param value="{'laoqiang3','laoqiang4','laoqiang5'}"></s:param>
</s:merge>
</table>
<s:iterator value="#list" var="list1">
<tr>
<td>
<s:property value="#list1"></s:property>
</td>
</tr>
</s:iterator>
</table>
subset
subset标簽用于取得集合的子集。
- count: 這是一個可選屬性,該屬性指定子集中元素的個數。如果不指定該屬性,則預設取得源集合的全部元素。
- source:這是一個可選屬性,該屬性指定源集合。如果不指定該屬性,則預設取得ValueStack棧頂的集合。
- start: 這是一個可選屬性,該屬性指定子集從源集合的第幾個元素開始截取。預設從第一個元素(即start 的預設值為0) 開始截取。
- decider:這是一個可選屬性,該屬性指定由開發者自己決定是否選中該元素。該屬性必須指定一個org.apache.struts2.utilSubsetteratorFiler.Decidr對象。
-
var: 這是- 一個可選屬性,如果指定了該屬性,則将生成的Iterator 對象設定成page 範圍的屬性。
該屬性也可替換成id,但推薦使用var 屬性。
在subset 标簽内時,subset 标簽生成的子集合放在ValueStack 的棧頂,是以我們可以在該标簽内直接疊代該标簽生成的子集合。如果該标簽結束後,該标簽生成的子集合将被移出ValueStack棧。
<s:subset source="{'laoqiang','laoqiang1','laoqiang2','laoqiang3','laoqiang4','laoqiang5'}" start="1" count="4">
<table border="2px">
<s:iterator>
<tr>
<td><s:property></s:property></td>
</tr>
</s:iterator>
</table>
</s:subset>
我們可以自己定義截取子集的規則:
public class MyDe implements Decider{
@Override
public boolean decide(Object arg0) throws Exception {
// TODO Auto-generated method stub
String s = (String)arg0;
return s.endsWith("3");
}
}
<s:bean var="myde" name="com.example.test.MyDe"></s:bean> //通過var把這個bean對象添加statck context中,自己可以用<s:debug/>看。
<s:subset source="{'laoqiang','laoqiang1','laoqiang2','laoqiang3','laoqiang4','laoqiang5'}" start="1" count="4" decider="#myde">//在Stack Context中擷取非根對象。
<table border="2px">
<s:iterator>
<tr>
<td><s:property></s:property></td>
</tr>
</s:iterator>
</table>
</s:subset>
<s:debug></s:debug>
- comparator : 這是- 一個必填的屬性,該屬性指定進行排序的Comparator 執行個體。
- source : 這是一個可選的屬性, 該屬性指定被排序的集合。如果不指定該屬性, 則對ValueStack 棧頂的集合進行排序。
- var: 這是一個可選的屬性, 如果指定了該屬性, 則将生成的Iterator 對象設定成page 範圍的屬性,不放入StackContext 中。該屬性也可替換成id,但推薦使用var 屬性。該屬性的作用與subset 标簽中var 屬性的作用相同。
public class MyCom implements Comparator {
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
return o2.toString().length()-o1.toString().length();
}
}
<s:bean var="mycom" name="com.example.test.MyCom"></s:bean>
<s:sort source="{'laoqiasdng','laoqiasdsdsng1','laoqiasdsdng2','laoqisdsdsdsang3','sdsdsd','laoqiandssg5'}" comparator="#mycom">
<table>
<s:iterator>
<tr>
<td><s:property/></td>
</tr>
</s:iterator>
</table>
</s:sort>
資料标簽
- action: 該标簽用于在JSP 頁面直接調用一個Action,通過指定executeResult 參數,還可将該Action的處理結果包含到本頁面中來。
- bean: 該标簽用于建立一個JavaBean 執行個體。如果指定了var 屬性,則可以将建立的JavaBean執行個體放入StackContext 中。
- date: 用于格式化輸出一個日期。
- debug: 用于在頁面上生成一個調試連結,當單擊該連結時,可以看到目前ValueStack 和Stack Context 中的内容。
- i18n: 用于指定國際化資源檔案的baseName.
- include: 用于在JSP 頁面中包含其他的JSP 或Servlet 資源。
- param: 用于設定一個參數,通常是用做bean标簽、ur|标簽的子标簽。
- push : 用于将某個值放入ValueStack 的棧頂。
- text: 用于輸出國際化消息。
- url: 用于生成一個URL 位址。
- property: 用于輸出某個值,包括輸出ValueStack、Stack Context 和Action Context 中的值。
Action
在Struts 2中提供了在Jsp中直接調用Action。
- var: 這是一個可選屬性,一旦定義了該屬性, 該Action 将被放入ValueStack 中, 該屬性可用id代替,但推薦使用var。
- name : 這是一個必填屬性,通過該屬性指定該标簽調用哪個Action。
- namespace : 這是一個可選屬性,該屬性指定該标簽調用的Action所在的namespace。這裡的namespace要和你在Struts.xml中填寫的一緻,否則會出問題。
- executeResult: 這是一一個可選屬性,該屬性指定是否要将Action的處理結果頁面包含到本頁面。該屬性值預設值是false, 即不包含。
- ignoreContextParams:這是一個可選參數,它指定該頁面中的請求參數是否需要傳入調用的Action。該參數的預設值是false,即将本頁面的請求參數傳入被調用的Action。
public class TagAction extends ActionSupport {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String execute1() throws Exception{
ActionContext.getContext().put("username",getUsername());//在這直接擷取url中的username參數。
return "DONE";
}
<s:action name="tag1" executeResult="true" namespace="/" />
<s:action name="tag2" executeResult="true" namespace="/" ignoreContextParams="false"/>ignoreContextParams設定為true,是不接受任何參數到Action。
采用Get方法攜帶參數:http://localhost:8889/StrutsTag/index.jsp?username=helloword,注意這裡的username,要和Action類的屬性一緻。
Bean
bean 标簽用于建立一個JavaBean 執行個體。建立JavaBean 執行個體時,可以在該标簽體内使用
<s:bean name="com.example.test.bean.Person">//這裡的javabean是存放在ValueStack
<s:param name="name" value="'laoqiang'"></s:param>//**注意這裡的字元你需要加單引号。**
<s:param name="age" value="12"></s:param>
<s:property value="'laoqiang'"/>
<s:property value="12"/>
</s:bean>
<s:bean name="com.example.test.bean.Person" var="personbean">//通過var将bean存放在stackcontext中,可以在<s:bean>外面去擷取它的值。同時也存放在requestScope
<s:param name="name" value="'laoqiang'"></s:param>
<s:param name="age" value="12"></s:param>
</s:bean>
<s:property value="#personbean.name"/>
<s:property value="#personbean.age"/>
Date
該标簽主要用于顯示時間。
- format: 這是一個可選屬性, 如果指定了該屬性, 将根據該屬性指定的格式來格式化日期。
- nice: 這是一個可選屬性,該屬性隻能為true或者false,它用于指定是否輸出指定日期和目前時刻之間的時差。該屬性預設是false,即表示不輸出時差。
- name : 這是一個必填屬性,該屬性指定要格式化的日期值。
- var: 這是一個可選屬性,如果指定了該屬性,格式化後的字元串将被放入Stack Context 中,并放入requestScope 中,但不會在頁面上輸出。該屬性也可用id 來代替,但推薦使用var。
<s:bean var="date" name="java.util.Date">//必須要導入這個javabean對象
</s:bean>
<s:date name="#date" format="yy/MM/dd"/></br>
<s:date name="#date" nice="true"/></br>
<s:date name="#date"/>//如果nice是預設false,并且沒有指定格式,是按照預設的struts時間格式顯示,這個修改可以到struts的常量配置修改
<s:date name="#date" var="time"/></br>//如果你指定var,是不顯示時間的,需要你通過s:property配置顯示。
<s:property value="#time"/></br>//下面的顯示都是按照預設的
${requestScope.time}
debug
該标簽主要用于調試ValueStack和Stack Context的值的變化。
include
将jsp或者Servlet導入到該檔案中。
<s:include value="index1.jsp">
<s:param name="username" value="'laoqiang'"></s:param>//可以傳參數給包含的Jsp頁面。
<s:debug/>
</s:include>
param
該标簽在Struts中主要可以攜帶參數,用法在之前都已經用過。這個标簽攜帶的參數是get傳遞。
其中,需要注意的傳入的是字元串,要在字元串的外面添加單引号。
push
該标簽将某個值放到ValueStack的棧頂,進而更簡單的通路該值。
隻有在push 标簽内時,被push 标簽放入ValueStack 中的對象才存在;一旦離開了push 标簽,則剛剛放入的對象将立即被移出ValueStack。
- value 該屬性是指定要放入ValueStack的值。
<s:bean name="com.example.test.bean.Person" var="person">
<s:param name="name" value="'laoqiang'"/>
<s:param name="age" value="123"/>
</s:bean>
//主要将一個javabean放入到StackContext,在将它放入到ValueStack中
<s:push value="#person">
<s:property value="name"/>
<s:property value="age"/>
</s:push>
Set
set 标簽用于将某個值放入指定範圍内,例如application 範圍、 session範圍等。當某個值所在對象圖深度非常深時,例如有如下的值: person.worker.wife.pareag 每次通路該值不僅性能低下,而且代碼可讀性也差。為了避免這個問題,可以将該值設定成一個新值,并放入特定的範圍内。
set 标簽可以了解為定義一個新變量,且将一個已有的值複制給新變量,并且可以将新變量放到指定的範圍内,原來對于Stack Context中,el表達式是不可以直接通路的。set 标簽用于生成一個新變量,并且把該變量放置到指定範圍内,這樣就允許直接使用JSP2 表達式語言來通路這些變量了,當然也可通過Struts2 标簽來通路它們。
-
scope: 這是- 一個可選屬性,指定新變量被放置的範圍,該屬性可以接受application,session、request.
page 或action 5個值。該屬性預設值是action。
- value: 這是- 一個可選屬性,指定将賦給變量的值。如果沒有指定該屬性,則将ValueStack棧頂的值賦給新變量。
- var: 這是一個可選屬性,如果指定了該屬性,則會将該值放入ValueStack 中。
當把指定值放入特定範圍時,範圍可以是application、session.request.page 和action 5 個值,前面4 個範圍很容易了解; 如果指定action 範圍, 則該值将被放入request 範圍中,并被放入OGNL 的Stack Context 中。
<s:bean name="com.example.test.bean.Person" var="person">
<s:param name="name" value="'laoqiang'"></s:param>
<s:param name="age" value="1234"></s:param>
</s:bean>
<s:set value="#person" var="newperson"/>//預設就是作用範圍是action,也就是request中
<s:property value="#newperson.name"/>
${requestScope.newperson.name}//注意el表示通路某個對象的屬性方式
${requestScope.person.name}//可以用set的新名字去通路,也可以用舊的名字去通路。
url
url 标簽用于生成一個URL 位址,可以通過為url 标簽指定param子元素,進而向指定URL 發送請求參數。
-
action: 這是一個可選屬性,指定生成URL 的位址為哪個Action,如果Action 不提供,就使用value 作為URL
的位址值。要想跳轉實際你定義的action,你需要把Struts.xml注冊的action的name,填寫在這。
- anchor: 這是一個可選屬性,指定URL 的錨點。
- encode: 這是一個可選屬性,指定是否需要對參數進行編碼,預設是true.
- escapeAmp: 這是一個可選參數,指定是否需要對&符号進行編碼,預設是true。
-
forceAddSchemeHostAndPort: 這是一個可選參數,指定是否需要在URL
對應的位址裡強制添加scheme、主機和端口。
- includeContext: 這是一個可選屬性,指定是否需要将目前上下文包含在URL 位址中。
-
includeParams :這是一個可選屬性, 該屬性指定是否包含請求參數,該屬性的屬性值隻能為none、get
或者all。該屬性值預設是get。
屬性值為get時,該url會将通路其所在jsp的的請求的所有get方法的參數添加到自身來。
屬性值為all時更是将get和post的的參數值全部添加到自身來。
一般我們并不需要額外的參數,是以定義為none。
- method: 這是一個可選屬性,該屬性指定Action 的方法。當我們用Action 來生成URL時,如果指定了該屬性,則URL将連結到指定Action 的特定方法。要想跳轉實際你定義的action,你需要把Struts.xml注冊的action的name,填寫在這。
-
namespace: 這是一個可選屬性,該屬性指定命名空間。當我們用Action 來生成URL 時,如果指定了該屬性,則URL
将連結到此namespace 的指定Action 處。
- portletMode: 這是一個可選屬性,指定結果頁面的portlet 模式。
- scheme : 這是一個可選屬性,用于設定scheme 屬性。
-
value: 這是一個可選屬性,指定生成URL 的位址值,如果value 不提供就用action 屬性指定的Action 作為URL
位址。
-
var: 這是一個可選屬性,如果指定了該屬性,将會把該連結值放入Struts 2 的ValueStack中。該屬性可用id
代替,但l推薦使用var。
- windowState: 這是一個可選屬性,指定結果頁面的portlet 的視窗狀态。
<s:url action="laoqiang">
<s:param name="name" value="'helloword'"/> /StrutsTag/laoqiang.action?name=helloword
</s:url>
</br>
<s:url value="laoqiang">
<s:param name="name" value="'helloword'"/>laoqiang?name=helloword 根據這個你應該看出value和action都是作為位址值,但是有所不同
</s:url>
</br>
<s:url>
<s:param name="name" value="'helloword'"/>/StrutsTag/index.jsp?name=helloword
</s:url>
</br>
<a href="<s:url includeParams="get" method="execute1" action="tag2" forceAddSchemeHostAndPort="true"/>"> fsdfdsfs</a>
//我們通過<s:url/>來創造一個url,放到<a href></a>就可以跳轉了
property
property 标簽的作用就是輸出指定值。property 标簽輸出value 屬性指定的值,如果沒有指定value屬性,則預設輸出ValueStack 棧頂的值。
- default: 這是一個可選屬性,如果需要輸出的屬性值為null,則顯示default 屬性指定的值。
Struts 2的模闆和主題
對于一個JSP 頁面裡包含的UI 标簽而言,既可以直接設定該UI 标簽需要使用的模闆, 也可以設定該UI 标簽使用的主題。實際上,對于界面開發者而言,并不推薦直接設定模闆屬性。因為模闆是以主題的形式組織在一起的,界面開發者應該選擇特定主題,而不是強制使用特定模闆來表現一個UI标簽。模闆是一個UI 标簽的外在表示形式。
主題是模闆的組織形式,模闆被包裝在主題裡面,對于開發者應該是透明的。當需要使用特定模闆來表現某個UI 标簽時,應讓主題來負責模闆的加載。
設定主題方式
- 通過設定特定UI 标簽上的theme 屬性來指定主題。
- 通過設定特定UI 标簽外圍的Form 标簽的theme 屬性來指定主題。
- 通過取得page 會話範圍内以theme 為名稱的屬性來确定主題。
- 通過取得session 會話範圍内的命名為theme 的屬性來确定主題。
- 通過取得application 會話範圍内的命名為theme 的屬性來确定主題。
-
通過設定名為struts.ui.theme 的常量(預設值是xhtml) 來确定預設主題,該常量可以在struts.properties
檔案或者struts.xml 檔案中确定。
上面的幾種指定特定UI 标簽主題的方式,它們是有着不同優先級的,排在前面的方式會覆寫排在後面的方式。例如,
我們通過特定UI 标簽上的theme 屬性指定了該标簽的主題,那麼後面指定的主題将不會起作用。
Struts 2 元素屬性
JavaScript 擁有屬性
滑鼠懸停的通用屬性
css設定屬性
表單元素的name于value屬性
每一個表單元素,都會映射成一個Action的屬性,是以在使用的一定要保證表單元素的name屬性值和對應Action的屬性值一緻,而一旦Action被執行個體化之後,Action的屬性值就是表單元素的value。
表單元素
-
checkboxlist
checkboxlist 标簽可以一次建立多個複選框,用于同時生成多個的HTML 标簽。它根據list 屬性指定的集合來生成多個複選框,是以,使用該标簽指定一個list 屬性。
listKey: 該屬性指定集合元素中的某個屬性(例如集合元素為Person 執行個體,指定Person 執行個體的name 屬性) 作為複選框的value.如果集合是Map,則可以使用key 和value 值指定Map 對象的key 和value 作為複選框的value.
listValue: 該屬性指定集合元素中的某個屬性(例如集合元素為Person 執行個體,指定Person執行個體的name 屬性) 作為複選框的顯示的選項名。如果集合是Map,則可以使用key 和value 值指定Map 對象的key 和value 作為複選框的标簽。
<s:checkboxlist name="a" list="{'laoqinag1','laoqiang2','laoqiang3'}" labelposition="top" />
<s:checkboxlist name="b" list="#{'name':'laoqiang','age':,'sex':'man'}" listKey="value" listValue="key"/>
<s:bean name="com.example.test.service.BookService" var="bs"/>//通過var,将這個bean添加到StatckContext中
<s:debug/>
<s:checkboxlist name="c" list="#bs.book" listKey="name" listValue="price"/>
上面的集合建立,包括方法的調用都是基于OGNL的,OGNL通路方法,該方法名必須是get開頭,調用的時候去除get,其他小寫。如果你建構集合,不是一個對象,就沒必要指定listKey,listValue,就比如第一種。
public class BookService {
public Book[] getbook(){
return new Book[]{
new Book("laohe",),
new Book("laohe1",),
new Book("laohe2",),
new Book("laohe3",),
};
}
}
-
doubleselect
doubleselect 标簽會生成個級聯清單框(會生成兩個下拉列框),當選擇第一個下拉清單框時,第: 二個下拉清單框的内容會随之改變。
<s:set var="bs11" value="#{'person': {'name','age','sex'},'teacher':{'laoqiang','teacherage'},'stuname':{'laopi','stuage'}}"/>
<s:form>
<s:doubleselect name ="d" list="{'laohe','laoqiang'}" doubleList="top=='laohe' ? {'laohe1','laohe2'} : {'laoqqiag1','laoqiang2'}" doubleName="e"/>
//top 是第一個框中的選中的值,通過#bs11[top],map的鍵來擷取。
<s:doubleselect name="f" size="3" list="#bs11.keySet()" doubleList="#bs11[top]" doubleSize="3" doubleName="g"/>
</s:form>
第一個下拉清單框隻支援兩組值,如果第一個下拉清單框包含三個或更多的值,這在預設情況下,
裡的list 和doubleList 屬性就不能這樣直接設定了。我們采用的是map。
-
optiontransferselet
optiontransferselet 會生成兩個清單選擇框,并生成系列的按鈕用于控制各選項在兩個下拉清單之間的移動、升降等。當送出該表單時,兩個清單選擇框對應的請求參數都會被送出。
<s:optiontransferselect label="你喜歡的圖書" name="optbook" leftTitle="中國圖書" rightTitle="外國圖書" list="{'java','wp','ss','po'}"
multiple="true" addAllToLeftLabel="全部向左移動" selectAllLabel="全部選擇" addAllToRightLabel="全部向右移動" doubleList="{'ppp','www',,'rrrr','tttt'}"
doubleName="rightbook" doubleMultiple="true"
/>
這個标簽都是封裝好的,你直接對照屬性使用就好。
- select
該标簽是生成一個下拉清單,基本用法和上面doubleselect 一緻。
- 清單内容
radio 标簽的用法與checkboxlist 的用法幾乎完全相同,一樣可以指定label.list、listKey 和listValue等屬性。與checkboxlist 唯一不同的是,checkboxlist 生成多個複選框,而radio 生成多個單選鈕。
<s:radio name="u" list="{'laohe','loaqinag','jiusjb','plkninb'}"/>
//如果是普通的集合無需指定listkey和listvalue
-
optgroup
optgroup 标簽用于生成一個下拉清單框的選項組,是以,該标簽必須放在selec…标簽中使用。一個下拉清單框中可以包含多個選項組,是以可以在一個select…>标簽中使用多個
<s:form>
<s:select name="rr" list="{'laohe','laoqiang','laoki','laopo'}" >
<s:optgroup label="選項組" list="#{'name':'laohe','sex':'man'}" listKey="key" listValue="value">
</s:optgroup>
<s:optgroup label="選項組1" list="#{'name1':'laohe1','sex1':'man1'}" listKey="key" listValue="value">
//label屬性是設定選項組名字的,不可以選中哦
</s:optgroup>
</s:select>
</s:form>//下拉需要放在form中
-
token
這是一個用于防止多次送出表單的标簽,token标簽能阻止多次送出表單的問題(避免重新整理頁面導緻的多次送出)。如果需要該标簽起作用,則應該在Struts2 的配置檔案中啟用TokenInterceptor攔截器或TokenSessionStorel nterceptor 攔截器。token 标簽的實作原理是在表單中增加一個隐藏域,每次加載該頁面時,該隐藏域的值都不相同。TokenInterceptor 攔截器則攔截所有使用者請求,如果兩次請求時該token 對應隐藏域的值相同(前一次送出時token 隐藏域的值儲存session 裡),則阻止表單送出。
預設情況下,token 标簽生成的隐藏域的name 為struts.token.不要在表單中是以,另外再定義一個名為struts.token 的表單域。
<package name="default" extends="struts-default" namespace="/">
<action name="token" class="com.example.test.action.TestToken">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="token"/>
<result name="invalid.token">/refresh.jsp</result>
<result name="success">/show.jsp</result>
</action>
</package>
上面配置檔案中使用了2 個攔截器,其中defaultStack 是系統預設的攔截器棧。看似前面Struts2 應用都沒有使用該攔截器,實際上該攔截器預設會生效; 此處因為顯式使用了token 攔截器,是以必須顯式配置使用defaultStack 攔截器,否則它不會預設生效。關于攔截器介紹請看下一章内容。另: 如果表單頁沒有使用标簽,則千萬不要使用token 攔截器,否則它将導緻無法送出表單。
updownselect
updownselect 标簽的用法非常類似于select 标簽的用法,差別是該标簽生成的清單框可以上下移動選項。是以使用該标簽時,一樣可以指定list.listKey 和listValue 等屬性,這些屬性的作用與使用select 标簽時指定的list、listKey 和listValue 等屬性完全相同。
<s:form>
<s:updownselect name="a" labelposition="top" label="請選擇" moveUpLabel="向上移動" moveDownLabel="向下移動" list="{'laoqiang','laoqiang2','laoqiang3'}"/>
<s:updownselect name="b" labelposition="top" label="請選擇2" moveUpLabel="向上移動" emptyOption="true" moveDownLabel="向下移動" list="#{'name':'laohe','age':'23','sex':'man'}" listKey="key" listValue="value"/>
<s:bean name="com.example.test.service.BookService" var="bs2"></s:bean>
<s:updownselect name="c" labelposition="top" label="請選擇3" moveUpLabel="向上移動" emptyOption="true" moveDownLabel="向下移動" list="#bs2.book" listKey="key" listValue="value"/>
</s:form>
注意在使用StackValue中的對象執行個體作為list集合是不需要加{ }的,加{ }的OGNL表達式構造的集合。
emptyOption 在清單構造一個空的選項。
非表單标簽
非表單标簽主要用于在頁面中生成一些非表單的可視化元素,例如Tab 頁面、輸出HTML頁面的樹形結構等。當然,非表單标簽也包含在頁面中顯示Action 裡封裝的資訊。
- actionerror: 如果Action 執行個體的getActionErrors()方法傳回不為null,則該标簽負責輸出該方法傳回的系列錯誤。
- actionmessage: 如果Action執行個體的getActionMessages()方法傳回不為null,則該标簽負責輸出該方法傳回的系列消息。
- component: 使用此标簽可以生成一個自定義元件。
- fielderror: 如果Action 執行個體存在表單域的類型轉換錯誤、校驗錯誤,該标簽則負責輸出這些。
public class TestActionMessage extends ActionSupport {
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
addActionError("錯誤資訊1");//可以看出添加資訊就類似在集合中添加資料,在顯示的時候,集合是通過有序清單進行顯示。
addActionError("錯誤資訊2");
addActionMessage("這是普通消息1");
addActionMessage("這是普通消息2");
return SUCCESS;
}
@Override
public Collection<String> getActionErrors() {
// TODO Auto-generated method stub
return super.getActionErrors();
}
@Override
public Collection<String> getActionMessages() {
// TODO Auto-generated method stub
return super.getActionMessages();
}
}
配置action
<action name="testmessage" class="com.example.test.action.TestActionMessage">
<result name="success">/show.jsp</result>//name屬性要和配置的actionname一緻。
</action>
<s:action name="testmessage" executeResult="true" namespace="/"></s:action>//executeResult是action1執行結果包含在本頁面中。
action中ignoreContextParam:可選參數,指定該頁面的請求參數是否需要傳入調用的Action中,預設值是false,
namespace 是防止你在配置多個package下的action重名問題。
component
component 标簽可用于建立自定義視圖元件,這是一個非常靈活的用法。如果開發者經常需要使用某個效果片段, 就可以考慮将這個效果片段定義成一個視圖元件,然後在頁面中使用component 标簽來使用該自定義元件。
- theme : 自定義元件所使用的主題, 如果不指定該屬性, 則預設使用xhtml 主題。
- templateDir: 指定自定義元件的主題目錄,如果不指定, 則預設使用系統的主題目錄, 即template 目錄。
-
template: 指定自定義元件所使用的模闆。
除此之外,還可以在cmponent 标簽内使用param子标簽,子标簽表示向該标簽模闆中傳入額外的參數。如果希望在模闆中取得該參數,總是采用: parameters.paramNam或者 p a r a m e t e r s . p a r a m N a m 或 者 parameters[param形式。
下面我們先來說第一種模闆,采用預設系統的主題目錄,系統的模闆檔案你可以把struts-core 核心的jar解壓,就可以看到在一個template/xhtml (xhtml 是代表的是主題)
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<div>
<s:debug/>
<s:select list="parameters.list1">//這個下拉清單的資料是通過list1來傳進來的
</s:select>
</div>
<s:component template="MyTemplate.jsp" >
<s:param name="list1" value="{'laoeh2','laohe3','laohe4'}"/>
</s:component>
在這裡我特别需要說的就是你編寫的目錄路徑,必須和系統的那個命名一緻,且必須放置在webroot下,也就是根目錄,絕對不可以是其他路徑,否則web是加載不到模闆檔案,因為采用系統的主題,它會到指定的template/xhtml下檢索。
如果采用自定義主題,那就easy多了。
<s:component templateDir="templateDir" theme="customtheme" template="MyAnotherTemplate.jsp" >
<s:param name="list" value="{'laoeh6','laohe8','laohe9'}"/>
</s:component>
<div>
<select>
<s:iterator value="%{top.parameters.list}">//因為參數會添加到棧值中,top取棧頂元素
<option><s:property/></option>
</s:iterator>
</select>
</div>
<s:component templateDir="templateDir" theme="customtheme" template="MyAnotherTemplate.jsp" >
<s:param name="list" value="{'laoeh6','laohe8','laohe9'}"/>
</s:component>
這回你把模闆檔案随便放在哪多行,但是要在webroot這個根目錄下,其他路徑下,需要添加對應的路徑。
需要注意在使用自定義模闆的時候,需要建立兩個檔案夾,一個對應templateDir,子檔案夾對應theme。
可以看出這種方式靈活,但是也有缺點,就是使用自定義主題,原有的struts的主題,路徑都不會加載,在上面的代碼中無法使用了。