理解ActionContext 、ValueStack 、Stack Context
ActionContext
一次Action調(diào)用都會創(chuàng)建一個(gè)ActionContext
調(diào)用:ActionContext context = ActionContext.getContext()
ValueStack
由OGNL框架實(shí)現(xiàn)
可以把它簡單的看作一個(gè)棧(List) 。
Stack Object:放入stack中的對象,一般是action。
Stack Context(map):stack上下文,它包含一系列對象,包括request/session/attr/application map等。
EL:存取對象的任意屬性,調(diào)用對象的方法,遍歷整個(gè)對象結(jié)…
ActionContext是Action上下文,可以得到request session application
ValueStack是值棧 存放表單中的值
Stack Context 棧上下文 也是用來存值的
struts2對OGNL上下文的概念又做了進(jìn)一步擴(kuò)充,在struts2中,OGNL上下文通常如下所示:
|--request
|
|--application
|
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|--session
|
|--attr
|
|--parameters
在Struts2中,采用標(biāo)準(zhǔn)命名的上下文(Context)來處理OGNL表達(dá)式。處理OGNL的頂級對象是一個(gè)Map(也叫context map),而OGNL在這個(gè)context中就是一個(gè)頂級對象(root)。在用法上,頂級對象的屬性訪問,是不需要任何標(biāo)記前綴的。而其它非頂級的對象訪問,需要使用#標(biāo)記。
Struts2框架把OGNL Context設(shè)置為我們的ActionContext。并且ValueStack作為OGNL的根對象。除value stack之外,Struts2框架還把代表application、session、request這些對象的Map對象也放到ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的原因,他可以通過ActionContext對象來部分代替這些(Servlet API)功能,以方便對Action類進(jìn)行測試!)
Action的實(shí)例,總是放到value stack中。因?yàn)?/span>Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標(biāo)記。但是,要訪問ActionContext中其它對象的屬性,就必須要帶上#標(biāo)記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。
那么訪問Action中的屬性的代碼就可以這樣寫
<s:property value="postalCode"/>
其它ActionContext中的非根對象屬性的訪問要像下面這樣寫:
<s:property value="#session.mySessionPropKey"/> or
<s:property value="#session['mySessionPropKey']"/> or
<s:property value="#request['myRequestPropKey']"/>
對Collection的處理,內(nèi)容就很簡單。
<s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />
這是處理List。這個(gè)代碼在頁面上建立一個(gè)下拉選項(xiàng),內(nèi)容是list中的內(nèi)容,默認(rèn)值是name2.
處理map
<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />
需要注意的是,判斷一個(gè)值是否在collection中。我們要使用in或者not in來處理。
<s:if test="'foo' in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
另外,可以使用通配符來選擇collection對象的子集。
?——所有匹配選擇邏輯的元素
^——只提取符合選擇邏輯的第一個(gè)元素
$——只提取符合選擇邏輯的最后一個(gè)元素
person.relatives.{? #this.gender == 'male'}
?
?
值棧(ValueStack)
Struts2將OGNL上下文設(shè)置為Struts2中的ActionContext(內(nèi)部使用的仍然是OgnlContext),并將值棧設(shè)為OGNL的根對象。
我們知道,OGNL上下文中的根對象可以直接訪問,不需要使用任何特殊的“標(biāo)記”,而引用上下文中的其他對象則需要使用“#”來標(biāo)記。由于值棧是上下文中的根對象,因此可以直接訪問。那么對于值棧中的對象該如何訪問呢?Struts2提供了一個(gè)特殊的OGNLPropertyAccessor,它可以自動(dòng)查找棧內(nèi)的所有對象(從棧頂?shù)綏5?/span>),直接找到一個(gè)具有你所查找的屬性的對象。也就是說,對于值棧中的任何對象都可以直接訪問,而不需要使用“#”。
假設(shè)值棧中有兩個(gè)對象:student和employee,兩個(gè)對象都有name屬性,student有學(xué)號屬性number,而employee有薪水屬性salary。employee先入棧,student后入棧,位于棧頂,那么對于表達(dá)式name,訪問的就是student的name屬性,因?yàn)?/span>student對象位于棧頂;表達(dá)式salary,訪問的就是employee的salary屬性。正如你所見,訪問值棧中的對象屬性或方法,無須指明對象,也不用“#”,就好像值棧中的對象都是OGNL上下文中的根對象一樣。這就是Struts2在OGNL基礎(chǔ)上做出的改進(jìn)。
值棧中的Action實(shí)例
Struts2框架總是把Action實(shí)例放在棧頂。因?yàn)?/span>Action在值棧中,而值棧又是OGNL中的根,所以引用Action的屬性可以省略“#”標(biāo)記,這也是為什么我們在結(jié)果頁面中可以直接訪問Action的屬性的原因。
Struts2中的命名對象
Struts2還提供了一些命名對象,這些對象沒有保存在值棧中,而是保存在ActionContext中,因此訪問這些對象需要使用“#”標(biāo)記。這些命名對象都是Map類型。
parameters
用于訪問請求參數(shù)。如:#parameters['id']或#parameters.id,相當(dāng)于調(diào)用了HttpServletRequest對象的getParameter()方法。
注意,parameters本質(zhì)上是一個(gè)使用HttpServletRequest對象中的請求參數(shù)構(gòu)造的Map對象,一量對象被創(chuàng)建(在調(diào)用Action實(shí)例之前就已經(jīng)創(chuàng)建好了),它和HttpServletRequest對象就沒有了任何關(guān)系。
request
用于訪問請求屬性。如:#request['user']或#request.user,相當(dāng)于調(diào)用了HttpServletRequest對象的getAttribute()方法。
session
用于訪問session屬性。如:#session['user']或#session.user,相當(dāng)于調(diào)用了HttpSession對象的getAttribute()方法。
application
用于訪問application屬性。如:#application['user']或#application.user,相當(dāng)于調(diào)用了ServletContext的getAttribute()方法。
attr
如果PageContext可用,則訪問PageContext,否則依次搜索request、session和application對象。
假設(shè)你的Action類中有變量String password; 要想獲取頁面中傳過來的password,必須為password設(shè)置get 和set 方法。當(dāng)你的頁面進(jìn)入Action時(shí),ActionContext(Action上下文)通過set方法獲取password的值并壓入值棧棧頂,同時(shí)request也獲取到password的值,同時(shí)也如堆棧,session等對象的值也被壓入堆棧,ActionContext中的值在頁面中可以直接用<s:porperty value="password">取值顯示,而request中存儲的password通過<s:porperty value="#request.password">或者${password}取值。即struts是通過一個(gè)值棧來存儲所有對象和ActionContext中的值得。ActionContext為棧頂對象,也稱跟對象,ActionContext的值可以直接用變量名取,而其他的變量需要用#變量名取值。
posted on 2014-01-09 11:20
kelly 閱讀(477)
評論(0) 編輯 收藏 所屬分類:
java 框架