二十三、OGNL表達(dá)式-Object Graphic Navigation Language(對象圖導(dǎo)航語言)
是Struts2框架默認(rèn)的表達(dá)式語言—其實(shí)我們可以不掌握OGNL表達(dá)式,JSTL/EL來代替
相對EL表達(dá)式,它提供了平時(shí)我們需要的一些功能,如:
1. 支持對象方法調(diào)用。如xxx.sayHello()
2. 支持類靜態(tài)方法調(diào)用和值訪問,表達(dá)式的格式為@[類全名(包括包路徑)]@[方法名|值名],例如:@java.lang.String@format(‘foo%s’, ‘bar’)或者
@cn.itcast.Constant@APP_NAME
1. 操作類對象
ognl有一個(gè)上下文(Context)概念,說白了上下文就是一個(gè)MAP結(jié)構(gòu),它實(shí)現(xiàn)了java.utils.Map接口,在Struts2中上下文(Context)的實(shí)現(xiàn)為ActionContext,下面是上下文(Context)的結(jié)構(gòu)示意圖
Struts2中的OGNL實(shí)現(xiàn)者為AcionContext
當(dāng)Struts2接收一個(gè)請求時(shí),會(huì)迅速創(chuàng)建ActionContext,ValueStack,action,然后把action存放進(jìn)ValueStack,所以action的實(shí)例變量可以被OGNL訪問
訪問上下文(Context)中的對象徐傲使用#符號標(biāo)注命名空間,如#application,#session
另外OGNL會(huì)設(shè)定一個(gè)根對象(root對象),在Struts2中根對象就是ValueStack(值棧),如果要訪問根對象(即ValueStack)中對象的屬性,則可以省略#命名空間,直接訪問該對象的屬性即可。
在Struts2中,根對象ValueStack的實(shí)現(xiàn)為OgnlValueStack,該對象不是我們想象的只存放單個(gè)值,而是存放一組對象。在OgnlValueStack類里有一個(gè)List類型的root變量就是使用他存放一組對象。
在root變量中處于第一位的對象叫棧頂對象,通常我們在OGNL表達(dá)式里直接寫上屬性的名稱即可訪問root變量里對象的屬性,搜索順序是從棧頂對象開始尋找,如果棧頂對象不存在該屬性,就會(huì)從第二個(gè)對象尋找,如果沒有找到就到第三個(gè)對象尋找,依次往下訪問,知道找到為止。
注意:Struts中,OGNL表達(dá)式是需要配合Struts標(biāo)簽才能使用,如:<s:property value=”name”/>
由于ValueStack(值棧)是Struts2中OGNL的根對象,如果用戶需要訪問值棧中的對象,在JSP頁面可以直接通過下面的EL表達(dá)式訪問ValueStack(值棧)中對象的屬性:
${foo} //獲得值棧中某個(gè)對象的foo屬性
如果訪問其他Context中的對象,由于他們不是根對象,所以在訪問時(shí),需要添加#前綴
application對象:用于訪問ServletContext,例如#application.userName或者#application[‘userName’],相當(dāng)于調(diào)用ServletContext的getAttribute(“username”)
session對象:用來訪問HttpSession。例如#session.userName或者#session[‘userName’],相當(dāng)于調(diào)用session.getAttribue(“userName”)
request對象:用來訪問HttpServletRequest屬性(attribute)的Map,例如#request.userName或者#request[‘userName’],相當(dāng)于調(diào)用request.getAttribute(“username”)
parameters對象:用于訪問HTTP的請求參數(shù),例如#parameters.userName或者
#parameters[‘userName’],
相當(dāng)于調(diào)用request.getParameter(“username”)
attr對象:用于按page->request->session->application順序訪問其屬性
為什么EL表達(dá)式能夠訪問valueStack中對象的屬性?
因?yàn)?/span>Struts2對HttpServletRequest做了進(jìn)一步的封裝
采用OGNL,不能訪問四大作用域中的變量,只能訪問ValueStack中的變量
采用OGNL表達(dá)式創(chuàng)建一個(gè)List/Map集合對象
如果需要一個(gè)集合元素的時(shí)候(例如List對象或者Map對象),可以使用OGNL中同集合相關(guān)的表達(dá)式。
例如使用如下代碼直接生成一個(gè)List對象:
<s:set name=”list” value=”{‘zhangming’,’xiaoli’,’liming’}”/>
<s:iterator value=”#list”>
<s:property /><br/>
</s:iterator>
set標(biāo)簽用于將某個(gè)值放入指定范圍
scope:指定變量被放置的范圍,該屬性可以接受application、session、request、page或者action。如果沒有設(shè)置該屬性,則默認(rèn)放置在OGNL Context中
value:賦給變量的值,如果沒有設(shè)置該屬性,則將valueStack棧頂?shù)闹蒂x給變量
生成一個(gè)Map對象
<s:set name=”foobar” value=”#{‘foo1’:’bar1’,’foo2’:’bar2’}” />
<s:iterator value=”#foobar” >
<s:property value=”key”>=<s:property value=”value”/>
</s:iterator>
采用OGNL表達(dá)式判斷對象是否存在于集合中:
對于集合類型,OGNL表達(dá)式可以使用in和not in兩個(gè)元素符號,其中,in表達(dá)式用來判斷某個(gè)元素是否在指定的集合對象中,not in判斷某個(gè)元素是否不在指定的集合對象中,如下所示。
in表達(dá)式:
<s:if test=”’foo’ in {‘foo’,’bar’}>
zai
</s:if>
<s:else>
bu zai
</s:else>
not in 表達(dá)式:
<s:if test”’foo’ not in {‘foo’,’bar’}>
bu zai
</s:if>
<s:else>
zai
</s:else>
OGNL表達(dá)式的投影功能---一般不適用,我們一般會(huì)在業(yè)務(wù)層把滿足條件的對象歸結(jié)出來
除了in和not in之外,OGNL還允許使用某個(gè)規(guī)則獲得集合對象的子集,場用的有以下3個(gè)相關(guān)操作符。
?:獲得所有符合邏輯的元素
^:獲得符合邏輯的第一個(gè)元素
$:獲得符合邏輯的最后一個(gè)元素
例如代碼:
<s:iterator value=”books.{?#this.price > 35}”>
<s:property value=”title”/>-$<s:property value=”price” /><br/>
</s:iterator>
在上面的代碼中,直接在集合后緊跟.{}運(yùn)算符取出該集合的子集,{}內(nèi)的表達(dá)式用于獲取符合條件的元素,this指的是為了從大集合books篩選數(shù)據(jù)到小集合,需要對大集合books進(jìn)行迭代,this代表當(dāng)前迭代的元素。本例的表達(dá)式用于獲取集合中價(jià)格大于35的書集合
books.{?#this.price > 35}
books.{……}: 要從大集合中,篩選出滿足……這個(gè)條件的子集合放到value中
?:表示符合邏輯的元素
#this:迭代大集合的當(dāng)前元素
二十四、Struts2 標(biāo)簽使用
property標(biāo)簽使用
<s:set name=”name” value=”kk” />
<s:property value=”#name” />
default:可選屬性,如果需要輸出的屬性值為NULL,則顯示該屬性指定的值
escape:可選屬性,指定是否格式化HTML代碼。
value:可選屬性,指定需要輸出的屬性值,如果沒有指定該屬性,則默認(rèn)輸出valueStack棧頂?shù)闹?/span>
id:可選屬性,指定該元素的標(biāo)識
iterator 迭代標(biāo)簽
iterator標(biāo)簽對于集合進(jìn)行迭代,這里的集合包含List、Set和數(shù)組
<s:set name="list" value="{'zhangming','xiaoi','liming'}"/>
<s:iterator value="#list" status="st">
<font color=<s:if test="#st.odd">red</s:if><s:else>blue</s:else>>
<s:property /></font>/<br>
</s:iterator>
value:可選屬性,指定被迭代的集合,如果沒有設(shè)置該屬性,則使用ValueStack棧頂?shù)募?/span>
id:可選屬性,指定集合里元素的id(已被標(biāo)注為過時(shí))
status:可選屬性,該屬性指定迭代時(shí)的iteratorStatus實(shí)例,該實(shí)例包含如下幾個(gè)方法:
int getCount(),返回當(dāng)前迭代了幾個(gè)元素
int getIndex(),返回當(dāng)前迭代元素的索引
Boolean isEven(),返回當(dāng)前被迭代元素的索引是否是偶數(shù)
Boolean isOdd(),返回當(dāng)前被迭代元素的索引是否是奇數(shù)
Boolean isFirst(),返回當(dāng)前被迭代元素是否是第一個(gè)元素
Boolean isLast(),返回當(dāng)前被迭代元素是否是最后一個(gè)元素
if/elseif/else 邏輯判斷
s:set name="age" value="323" scope="request"/>
<s:if test="#request.age==23">
23
</s:if>
<s:elseif test="#request.age==21">
21
</s:elseif>
<s:else>
都不等
</s:else>
url標(biāo)簽
<a href="<s:url action="helloworld_add" namespace="/test"><s:param name="personid" value="233"/></s:url>">ssss</a>
<s:set name="myurl" value="'http://www.foshanshop.net'"/>
<s:url value="%{#myurl}" /><br>
checkboxlist復(fù)選框/radio 單選框/select下拉列表框
集合為list:
<s:checkboxlist name="list"
list="{'Java','.Net','RoR','PHP'}" value="{'Java','.Net'}"/><br/>
集合為map:
<s:checkboxlist name="map" list="#{1:'瑜珈用品',2:'戶外用品',3:'球類',4:'自行車'}"
listKey="key" listValue="value" value="{1,2,3}"/><br/>
<s:radio name="raido1" list="#{1:'瑜珈用品',2:'戶外用品',3:'球類',4:'自行車'}" listKey="key" listValue="value" value="1"/>
<br/>
<s:select name="se" list="#{1:'瑜珈用品',2:'戶外用品',3:'球類',4:'自行車'}" listKey="key" listValue="value" value="1"/>
<!-- 默認(rèn)的視圖主題,即不需要struts2在頁面為我們輸出一些代碼 -->
<constant name="struts.ui.theme" value="simple" />
二十五、國際化
目前對筆者不適用,由于時(shí)間緊迫,不再記錄