Struts2中的OGNL表達式

值棧

<li>ValueStack對象相當于一個棧邓线,它貫穿整個Action的生命周期淌友,每個Action類的對象實例都會擁有一個ValueStack對象。當Struts2接收到一個*.action請求后骇陈,并不是直接調用Action方法震庭,而是先將Action類的相應屬性放到ValueStack對象的頂層節(jié)點
值棧也位于內存中,它也是和parameters你雌、request器联、session、application婿崭、attr對象放在一起的拨拓。值棧屬于ONGL Context里面的根對象。也就是說它位于整個內存中最最重要的地方氓栈,所以叫根對象渣磷。根對象和另外五個對象是有區(qū)別的,根對象可以省寫#號授瘦,比如<s:property value="user.username"/>醋界。值棧的生命周期與request請求相關,每次請求產(chǎn)生一個值棧提完。默認所有的Action會被自動放到值棧里形纺。

服務器跳轉時共用值棧

假設從一個Action11通過服務器跳轉到Action22的話,就意味著這兩個Action是共享一個值棧的徒欣,因為一次請求只使用一個值棧逐样。這時內存中情況是這樣的:首先接收到Action11請求后,會產(chǎn)生一個值棧帚称,在棧頂存放Action11對象以及它所有的屬性官研。然后經(jīng)過服務器跳轉到Action22,這時就會把Action22對象壓入值棧的棧頂位置闯睹,此時Action11對象以及它的所有屬性就位于棧底了戏羽。

取值過程

棧的特征是后進先出。于是首先到棧頂?shù)膶ο罄锊檎沂欠翊嬖谶@個屬性楼吃,如果棧頂?shù)腁ction22對象中不存在這個屬性的話
它就會繼續(xù)向下尋找直至棧底對象始花,一直查找是否存在這個屬性
如果最后找到該屬性的話芦缰,那么就會在JSP頁面中通過<s:property value="username"/>輸出屬性值
如果在Action22和Action11都有一個同名的同類型的username屬性的話扰柠,那么將輸出Action22中的屬性值
因為它是先從棧頂開始尋找屬性的,值棧的特征就是后進先出器虾,但有個前提:請求過程是通過服務器跳轉的

三個語法

假設此時想要獲取Action11中的username屬性的話躬窜,就可以使用值棧的Top語法或者N語法
<li>使用Top語法獲取值棧中的第二個對象的屬性:<s:property value="[1].top.username"/>
<li>使用 N 語法獲取值棧中的第二個對象的屬性:<s:property value="[1].username"/>
<li>使用@語法調用Action中的靜態(tài)方法:<s:property value="@vs@getVOMethod()"/>
@vs@get()等價于@vs1@getVOMethod()浇垦,指的是棧頂對象的靜態(tài)getVOMethod()方法
同理@vs2@getVOMethod()就是取值棧中第二個對象的靜態(tài)getVOMethod()方法

客戶端跳轉時使用各自的值棧

假如中間某一個步驟中出現(xiàn)了客戶端跳轉的話,那么兩個Action所使用的就是兩個不同的值棧了荣挨。所以在Action22中就不能再使用Action11中的屬性了男韧,在最后跳轉到的JSP頁面中也就無法獲取Action11的屬性了朴摊。也即從Action22跳轉到JSP頁面時使用的是redirect的話,那么最后值棧中是沒有任何的Action對象的此虑。這個時候我們可以通過鏈接傳參甚纲,比如<result type="redirect">test.jsp?netname=${username}</result>,意思就是取出Action22中的username屬性作為參數(shù)朦前,通過瀏覽器地址欄傳遞到JSP頁面中然后使用OGNL中的#號獲取Paraments對象的屬性介杆,即<s:property value="#parameters.netname"/>就可以取到值了。

手工向值棧中壓入對象

正常情況下值棧保存的是Action對象韭寸,而我們也可以直接往值棧中添加其它對象春哨,這時可以在Action中添加如下代碼
向值棧中添加對象:

ActionContext.getContext.getValueStack().push(new Student("沈浪",22));

而且我們手工往值棧中添加的Student對象會位于棧頂。這是因為Struts2會首先初始化Action棒仍,然后才能調用它的方法悲靴。初始化Action的時候臭胜,便把Action放到值棧中了莫其,然后在執(zhí)行它的execute()方法時,就又往值棧中添加了Student對象耸三。


OGNL

OGNL是Object-Graph Navigation Language的縮寫乱陡,是一種功能強大的表達式語言。通過它簡單一致的表達式語法仪壮,可以存取對象的任意屬性憨颠,調用對象的方法,遍歷整個對象的結構圖积锅,實現(xiàn)字段類型轉化等功能爽彤。OGNL用得最多的地方就是和Struts2的標簽綁定,也可以在配置文件中通過${}使用OGNL表達式

OGNL中$號的使用

1.在國際化資源文件中缚陷,引用OGNL表達式
2.在struts.xml文件中适篙,引用OGNL表達式

OGNL中%號的使用

1.使用%{}可以取出保存在值堆棧中的Action對象,直接調用它的方法
2.如果Action繼承了ActionSupport箫爷,那么在頁面標簽中可以使用%{getText('key')}獲取國際化信息

OGNL中#號的使用

OGNL中的#號可以取出堆棧上下文中存放的對象

|名稱|作用|例子|
|---|---|---|
|attr|用于按request>>session>>application順序訪問其屬性|#attr.userName相當于按順序從三個范圍讀取userName屬性直到找到為止|
|request|包含當前HttpServletRequest的屬性的Map|#request.userName相當于request.getAttribute("userName")|
|session|包含當前HttpSession的屬性的Map|#session.userName相當于session.getAttribute("userName")|
|application|包含當前應用的ServletContext的屬性的Map|#application.userName相當于application.getAttribute("userName")|
|parameters|包含當前HTTP請求參數(shù)的Map|#parameters.id[0]相當于request.getParameter("id")|

獲取Action中的屬性值或者Action中的對象的某某屬性值

利用<s:property/>標簽可以直接獲取Action中的引用類型user里面的username屬性嚷节,同樣可以通過user.address.addr獲取user中引用類型address中的addr屬性的值,像這種一層一層往下傳遞的訪問方式虎锚,即所謂的導航硫痰,也就是一步步的往下調用。

調用Action的對象里面的普通方法

默認的會把Action放到值棧里面窜护,而值棧在訪問的時候效斑,并不需要值棧的名字。當我們調用

<s:property value="user.getVOMethod()"/>

的時候,它會自動到值棧里面查找Action對象里面有沒有user對象柱徙,然后它就發(fā)現(xiàn)有user,然后它就再找user里面有沒有getVOMethod()方法缓屠,然后它發(fā)現(xiàn)有税娜,于是調用getVOMethod().實際上調用User中的getVOMethod()方法的過程與獲取表單中的姓名密碼的方式都是相同的,都是到值棧里面查找,找是否存在user對象藏研,如果存在敬矩,接著查找user中是否存在某某屬性或方法.

調用Action中的靜態(tài)方法

同樣我們也可以在JSP頁面中寫一個OGNL表達式調用Action中的靜態(tài)方法。調用Action中的靜態(tài)方法時蠢挡,與調用user對象的getVOMethod()方法的過程弧岳,是截然不同的。此時value的寫法是固定的业踏,以@開頭禽炬,后面跟上具體的包名,然后@加上靜態(tài)方法
比如

<s:property value="@com.jadyer.action.LoginAction@getStatic()"/>

另外user對象是LoginAction中的一個屬性勤家,這個屬性會自動的放到值棧里面腹尖,而值棧調用的時候,不用加上@或者包名等等伐脖,所以直接user.getVOMethod()就可以了热幔。

調用JDK類中的靜態(tài)方法

可以使用<s:property value="@@floor(46.58)"/>輸出floor()的執(zhí)行結果這就意味著如果不在@@中指定類的話,默認的就表示Java.lang.Math類當前大多數(shù)情況下讼庇,我們都不會省略這個類绎巨,都會寫全了的,然后在后面加上靜態(tài)方法蠕啄。

集合的偽屬性

OGNL能夠引用集合的一些特殊的屬性场勤,這些屬性并不是JavaBean模式,例如size()歼跟、length()和媳。當表達式引用這些屬性時,OGNL會調用相應的方法哈街,這就是偽屬性留瞳。
比如獲取List的大小:

<s:property value="testList.size"/>

List的偽屬性:size叹卷、isEmpty撼港、iterator
Set的偽屬性:size、isEmpty骤竹、iterator
Map的偽屬性:size帝牡、isEmpty、keys蒙揣、values
terator的偽屬性:next靶溜、hasNext
Enumeration偽屬性:next、hasNext、nextElement罩息、hasMoreElements

獲取集合中元素的實質就是調用它的toString()方法

它還可以直接獲取集合中的元素嗤详,事實上是在調用集合的toString()方法,所以我們可以根據(jù)實際情況通過重寫集合的toString()方法來實現(xiàn)個性化輸出,甚至它還可以像訪問數(shù)組那樣,直接testList[2]獲取集合中的元素,但這種方法只適用于List瓷炮,不適用于Map葱色。因為Map的索引是key,不是數(shù)值.另外娘香,由于HashSet中的元素是沒有順序的苍狰,所以也不能用下標獲取單個元素.

Lambda表達式

補充一下:使用Lambda表達式可以在OGNL中書寫遞歸式子,在幫助中對它有很詳細的說明
打開幫助中的//struts-2.0.14-all//struts-2.0.14//docs//index.html頁面
在左側的Documentation下面點擊Guides鏈接烘绽,然后在這個頁面中點擊OGNL,最后跳轉到//struts-2.0.14-all//struts-2.0.14//docs//docs//ognl.html將這個頁面右側的下拉條拖放到最下面淋昭,就會看到它的說明了,它舉的例子如下所示.

<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />

Lambda表達式的語法是:[...] 安接,中括號前面有一個冒號翔忽,所有東西都在中括號里面寫,也就是說我們只要看到一個冒號跟著一個中括號,就表示這里使用的是Lambda表達式,#this指的是表達式的參數(shù),所以這個例子可以這樣理解:先判斷這個參數(shù)是否等于零盏檐,如果等于零歇式,那么它的值最后就是零.如果參數(shù)不等于零,就再判斷它是否等于壹糯笙。如果參數(shù)等于壹贬丛,那么它的值最后就是壹.如果參數(shù)不等于壹,就繼續(xù)調用#fib给涕。注意這里已經(jīng)用中括號將整體的值賦給了fib.實際上很少能夠用得到Lambda表達式.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市额获,隨后出現(xiàn)的幾起案子够庙,更是在濱河造成了極大的恐慌,老刑警劉巖抄邀,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耘眨,死亡現(xiàn)場離奇詭異,居然都是意外死亡境肾,警方通過查閱死者的電腦和手機剔难,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奥喻,“玉大人偶宫,你說我怎么就攤上這事』防穑” “怎么了纯趋?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我吵冒,道長纯命,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任痹栖,我火速辦了婚禮亿汞,結果婚禮上,老公的妹妹穿的比我還像新娘揪阿。我一直安慰自己留夜,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布图甜。 她就那樣靜靜地躺著碍粥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黑毅。 梳的紋絲不亂的頭發(fā)上嚼摩,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音矿瘦,去河邊找鬼枕面。 笑死,一個胖子當著我的面吹牛缚去,可吹牛的內容都是我干的潮秘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼易结,長吁一口氣:“原來是場噩夢啊……” “哼枕荞!你這毒婦竟也來了?” 一聲冷哼從身側響起搞动,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤躏精,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹦肿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矗烛,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年箩溃,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞭吃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡涣旨,死狀恐怖歪架,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情开泽,我是刑警寧澤牡拇,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響惠呼,放射性物質發(fā)生泄漏导俘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一剔蹋、第九天 我趴在偏房一處隱蔽的房頂上張望旅薄。 院中可真熱鬧,春花似錦泣崩、人聲如沸少梁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凯沪。三九已至,卻和暖如春买优,著一層夾襖步出監(jiān)牢的瞬間妨马,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工杀赢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烘跺,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓脂崔,卻偏偏與公主長得像滤淳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砌左,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容

  • 利用投影獲取屬性 利用投影獲取List中對象的username屬性時脖咐,其中{}表示的是一個集合.stus.{use...
    FTOLsXD閱讀 190評論 0 1
  • 概述 什么是Struts2的框架Struts2是Struts1的下一代產(chǎn)品,是在 struts1和WebWork的...
    inke閱讀 2,242評論 0 50
  • OGNL是一種表達式語言绊困,可以存取對象的屬性或者調用對象的方法文搂,能夠遍歷整個對象的結構圖,實現(xiàn)對象屬性類型的轉換等...
    yjaal閱讀 5,924評論 0 9
  • 1. Java基礎部分 基礎部分的順序:基本語法秤朗,類相關的語法,內部類的語法笔喉,繼承相關的語法取视,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 接下來必須改變的東西常挚。 思維——思維太過于局限了作谭,接下來,必須讓其開闊奄毡,看每一件事物的時候不能僅僅去看表面折欠,應該挖...
    拾壹束花閱讀 212評論 0 2