原文地址:http://blog.csdn.net/wyply115/article/details/8257140
一、OGNL表達(dá)式
1.ognl是struts2中使用的一種表達(dá)式語(yǔ)言,可用于jsp的標(biāo)簽庫(kù)中,以方便訪問(wèn)各種對(duì)象的屬性。它用于把界面的參數(shù)傳遞到Action中(并進(jìn)行類型轉(zhuǎn)換),它還可以用于struts2的配置文件中。
2. Root對(duì)象。
OGNL稱為對(duì)象圖導(dǎo)航語(yǔ)言,所謂對(duì)象圖,即以任意一個(gè)對(duì)象為根,通過(guò)OGNL可以訪問(wèn)與這個(gè)對(duì)象關(guān)聯(lián)的其它對(duì)象,例如:
public class User{ PRivate String username; private Group group; //省略setter,getter方法 } public class Group{ private String name; private Organization org; //省略setter,getter方法 } public class Organization{ private String orgId; //省略setter,getter方法 }
以上三個(gè)類,描述了通過(guò)User對(duì)象可以導(dǎo)航到Group對(duì)象,進(jìn)而導(dǎo)航到Organization對(duì)象。以User為根,通過(guò)基本的getters方法,可以訪問(wèn)到此根對(duì)象的其它關(guān)聯(lián)對(duì)象.【對(duì)象圖的導(dǎo)航,必須通過(guò)getters方法導(dǎo)航】。
注意:
* 導(dǎo)航的目的,就是為了獲取某個(gè)對(duì)象的值或設(shè)置某個(gè)對(duì)象的值或調(diào)用某個(gè)對(duì)象的方法.
* OGNL表達(dá)式語(yǔ)言的真正目的,是為了在那些不能寫java代碼的地方執(zhí)行java代碼,或者是為了更方便的執(zhí)行java代碼.
3.Context對(duì)象
* 在OGNL表達(dá)式中,有可能需要訪問(wèn)到多個(gè)毫不相干的對(duì)象,這時(shí)候,我們需要給OGNL傳遞一個(gè)Map類型的對(duì)象,把表達(dá)式中需要用到的對(duì)象放到Map中即可.而這個(gè)Map對(duì)象稱為Context。
* 要在表達(dá)式訪問(wèn)到context中的對(duì)象,需要使用"#對(duì)象名稱"的語(yǔ)法規(guī)則
* 存在context的主要原因就是在OGNL中,不支持多個(gè)root對(duì)象,而如果需要在表達(dá)式中訪問(wèn)多個(gè)毫不相關(guān)的對(duì)象時(shí),只能通過(guò)一個(gè)Map來(lái)把這些對(duì)象統(tǒng)一傳遞給OGNL。
二、ValueStack
1.ValueStack是一個(gè)接口,在struts2中使用OGNL(Object-Graph Navigation Language)表達(dá)式實(shí)際上是使用實(shí)現(xiàn)了ValueStack接口的類OgnlValueStack.它ValueStack的默認(rèn)實(shí)現(xiàn)類.
2.ValueStack貫穿整個(gè)action的生命周期,每一個(gè)action實(shí)例都擁有一個(gè)ValueStack對(duì)象,其中保存了當(dāng)前action對(duì)象和其他相關(guān)對(duì)象.
3.struts2把ValueStack對(duì)象保存在名為:struts.valueStack的request域中.即ValueStack作用域?yàn)閞equest.當(dāng)action創(chuàng)建的時(shí)候,ValueStack就創(chuàng)建了,action被銷毀的時(shí)候,ValueStack就銷毀了
4.ValueStack中的數(shù)據(jù)分兩部分存放:root(棧結(jié)構(gòu),CompoundRoot)和context(map形式,OgnlContext)
(1)
* 其中的root對(duì)象是CompoundRoot,CompoundRoot繼承了ArrayList,提供了額外的方法:push(),和pop()方法,用來(lái)對(duì)root對(duì)象中所包含的數(shù)據(jù)進(jìn)行存取.正是由于這兩個(gè)方法,CompoundRoot變成了一個(gè)棧結(jié)構(gòu).
* struts2中,一個(gè)請(qǐng)求在最終到達(dá)Action的方法之前,Action對(duì)象本身會(huì)被壓入ValueStack(實(shí)際上就是放到ValueStack 的CompoundRoot中),所以action對(duì)象是CompoundRoot中的一個(gè)元素.
(2)
* 其中的context對(duì)象是OgnlContext,它實(shí)現(xiàn)了map接口,在valuestack的默認(rèn)實(shí)現(xiàn)類中,即OgnlValueStack類中,調(diào)用ongl中的方法:Ognl.createDefaultContext(..)給context賦值,查看源代碼可知,此方法返回的是一個(gè)OgnlContext對(duì)象.
5.獲取ValueStack的三種方式
(1)ValueStack valueStack = ActionContext.getContext().getValueStack();
ActionContext為Action的上下文,其中有重要的6大對(duì)象valueStack,parameters,request,session,application,attr。而ognl表達(dá)式必須選擇AcitonContext中的一個(gè)對(duì)象作為根對(duì)象(root),默認(rèn)為valueStack,因此訪問(wèn)valueStack中的數(shù)據(jù)不加#,而如果要使用另外5個(gè)對(duì)象作為根對(duì)象,需要加#前綴。
(2)ValueStack valueStack = ServletActionContext.getValueStack(ServletActionContext.getRequest());
ServletActionContext繼承了ActionContext,它與web容器耦合,可以獲取web容器的一些信息.
(3)ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
因?yàn)閂alueStack被置于Request域中。
6.ValueStack內(nèi)存結(jié)構(gòu)圖
原博文圖涉及底層實(shí)現(xiàn)細(xì)節(jié),該圖是我簡(jiǎn)化后,原博文圖片(http://img.my.csdn.net/uploads/201212/04/1354620065_9013.png)
7.常用的存儲(chǔ)數(shù)據(jù)的方法
(1)向Map棧中存數(shù)據(jù),即ValueStack中的context中存儲(chǔ)數(shù)據(jù)。
通過(guò)request, session等向map中存儲(chǔ)數(shù)據(jù):
ServletActionContext.getRuquest().setAttribute("username","xxx") ;
ServletActionContext.getSession().put("pwd","123");
直接向Map棧中存放數(shù)據(jù):
ActionContext.getContext().put("msg","hello") ;
(2)向?qū)ο髼V写鏀?shù)據(jù),即ValueStack中的root(CompoundRoot)對(duì)象
* 先得到root,再把數(shù)據(jù)壓入到root中,這中方式是放入到棧底
ValueStack valueStack =ActionContext.getContext().getValueStack(); valueStack.getRoot().add(new Person());
* 先得到root,利用add(index,Object)把一個(gè)對(duì)象壓入到root中指定位置.
ValueStack valueStack =ActionContext.getContext().getValueStack(); valueStack.getRoot().add(0,new Person());//這里0,表示壓入棧頂.
* 存放一個(gè)map到對(duì)象棧中
ValueStack valueStack =ActionContext.getContext().getValueStack(); valueStack.set("msg","dude"); //先封裝成Map,在把Map放入到對(duì)象棧中,且放入棧頂.
* 利用valueStack的push方法把一個(gè)對(duì)象直接壓入棧頂
ValueStack valueStack =ActionContext.getContext().getValueStack();valueStack.push(new Person());
8.利用OGNL表達(dá)式取ValueStack中的數(shù)據(jù)
(1)<s:property />:取棧頂?shù)脑?
(2)<s:iterator />:取棧頂?shù)脑?
注意:此標(biāo)簽的value屬性值無(wú)論來(lái)自對(duì)象棧還是Map棧,都可以不加#前綴(<s:select/>標(biāo)簽也適用).
因?yàn)榇藰?biāo)簽在迭代的時(shí)候,總是把當(dāng)前正在迭代的元素放入到棧頂.
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注