衆所周知,Strut 2的Action類通過屬性可以獲得所有相關的值,如請求參數、Action 配置參數、向其他Action傳遞屬性值(通過chain結果)等等。要獲得這些參數值,我 們要做的唯一一件事就是在Action類中聲明與參數同名的屬性,在Struts 2調用Action 類的Action方法(默認是execute方法)之前,就會爲相應的Action屬性賦值。 要完成這個功能,有很大程度上,Struts 2要依賴於ValueStack對象。這個對象貫 穿整個Action的生命週期(每個Action類的對象實例會擁有一個ValueStack對象)。當 Struts 2接收到一個.action的請求後,會先建立Action類的對象實例,但並不會調用 Action方法,而是先將Action類的相應屬性放到ValueStack對象的頂層節點 (ValueStack對象相當於一個棧)。只是所有的屬性值都是默認的值,如String類型的 屬性值爲null,int類型的屬性值爲0等。 在處理完上述工作後,Struts 2就會調用攔截器鏈中的攔截器,當調用完所有的攔 截器後,最後會調用Action類的Action方法,在調用Action方法之前,會將ValueStack 對象頂層節點中的屬性值賦給Action類中相應的屬性。大家要注意,在這裏就給我們帶 來了很大的靈活性。也就是說,在Struts 2調用攔截器的過程中,可以改變ValueStack 對象中屬性的值,當改變某個屬性值後,Action類的相應屬性值就會變成在攔截器中最 後改變該屬性的這個值。 從上面的描述很容易知道,在Struts 2的的Action類可以獲得與屬性同名的參數值 就是通過不同的攔截器來處理的,如獲得請求參數的攔截器是params,獲得Action的配 置參數的攔截器是staticParams等。在這些攔截器內部讀取相應的值,並更新 ValueStack對象頂層節點的相應屬性的值。而ValueStack對象就象一個傳送帶,將屬性 值從一個攔截器傳到了另一個攔截器(當然,在這其間,屬性值可能改變),最後會傳 到Action對象,並將ValueStack對象中的屬性的值終值賦給Action類的相應屬性
甚是不解,求助於網上依然沒有得到解決! 花了點時間看了下源碼! 發現: struts2 參數攔載器在注入值的時候,有兩種機制,(調用ognl) 這是OgnlRuntime 類中一段源碼 hasSetMethod( context, target, targetClass, name ) || hasField( context, target, targetClass, name ); 他會先查看你的action 中有沒有對應的方法,如果發現無此方法,他會利用第二種方法 直接給屬性覆值,而無需對應的set方法!(當然都是通過反射機制實現的) 如果action 中屬性過多的話,我覺得就不用寫set get 方法了!(不知道這個會不會給以 後維護帶來問題). 個人總結:OGNL中的值棧相當於一個數據的中轉站,或者叫數據的緩衝存儲中心。另外,OGNL除了有值棧(VS)這個特別的對象外,它的表達式語言也自成一派。 值棧和session都是在ActionContext的全局領域內的,按我個人通俗的說法就是ActionContext最大,並且ActionContext中包含值棧和session這些全局的容器,因爲actioncontext是線程級的,那麼session就是線程安全的。
我們在jsp頁面是直接面向值棧操作,所以值棧的內容可以直接用名字來引用。值棧外的如session就要用OGNL語法中的#來操作。 對於值棧來說,struts2有專門的tag叫<s:property >來引用值棧內容,如下例: < session是值棧外的(全局的,或稱根級別),所以要用OGNL的#符號表達式來引用session裏的對象,如 < 可以先把一個變量級別升高成爲全局,然後用#符號來引用值,那麼用s:set標籤來做,如
< s:set name = "artistBio" value = "artist.bio" />
======》老子級別也高了,YEAH!! < b >Album Title :</ b > < s:property value = "title" />
< br > < b >Artist Name :</ b > < s:property value = "#artistName" /> < br > < b >Artist
Bio :</ b > < s:property value = "#artistBio" /> ===》級別高了,不在值棧內就不能直接引用了。。。。。需要加#號 假如想讓對象不但級別高了(全局的)在整個session週期內持久,就要加上scope,如
< s:set name = "artistBio" value = "artist.bio" scope = "session" /> < b >Album Title :</ b > < s:property value = "title" />
< br > < b >Artist Name :</ b > < s:property value = "#session['artistName']" />
< br > < b >Artist Bio :</ b > < s:property value = "#session['artistBio']" />
< br > 下面還有push標籤,用來把對象放到值棧頂端:
< s:push value = "artist" > < b >Artist Name :</ b > < s:property value = "name" />
< br > < b >Artist Bio :</ b > < s:property value = "bio" />
< br > </ s:push > 那麼<s:bean>這個標籤,用來在頁面實例化一個bean放在值棧中,它的生存週期就是到了</s:bean>爲止就結束了,所以說假如要用<s:property>這個標籤來引用該bean的屬性的話,一定要在<s:bean>和</s:bean>標籤之中用。如下面例子:
< s:param name = "dollars" value = "100" /> 100Dollars = < s:property value = "rupees" /> Rupees </ s:bean > 那麼假如在bean標籤之外引用呢,因爲這時候這個bean的生命週期結束了,已經不在值棧內了,所以要用的話,需要事先在前面bean的聲明地方加上一個變量聲明,使其成爲全局的對象,然後再像引用session變量那樣的方式來引用它,如下例:
< s:param name = "dollars" value = "100" ></ s:param > </ s:bean > 100 Dollars = < s:property value = "#converter.rupees" /> Rupees |
valuestack
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.