一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Struts2中OGNL,valueStack,stackContext的學習

 燮羽 2010-11-24
學習Struts2,一直不明白表單中的值是怎么傳給Action的,上網(wǎng)查了些資料,基本了解了!下面基本是從幾個人的BOLG轉載過來,以后記不清了再來看~ 
先看看我做的實驗
 
jsp頁面 
Java代碼 
  1. <s:form action="hello/converter.action" method="post">  
  2.         <s:textfield name="point" label="點"></s:textfield>  
  3.         <s:textfield name="point2" label="2"></s:textfield>  
  4.         <s:textfield name="point3" label="3"></s:textfield>  
  5.         <s:textfield name="age" label="年齡"></s:textfield>  
  6.         <s:textfield name="date" label="日期"></s:textfield>  
  7.         <s:submit name="提交"></s:submit>  
  8.     </s:form>  

結果圖(是通過<s:debug></s:debug>得到的) 
value stack: 。。自己去看。。
通過圖中我們可以看到 
valuestack中包括我傳遞的值(point,point2,point3,age,date) 
stack context中包括了 request application OgnlValueStack(root) session parameters 等屬性 

值棧(ValueStack)     
Struts2將OGNL上下文設置為Struts2中的ActionContext(內(nèi)部使用的仍然是OgnlContext),并將值棧設為OGNL的根對象?!   ?span id="vrnd3xt" class=Apple-converted-space> 
我們知道,OGNL上下文中的根對象可以直接訪問,不需要使用任何特殊的“標記”,而引用上下文中的其他對象則需要使用“#”來標記。由于值棧是上下文中的根對象,因此可以直接訪問。那么對于值棧中的對象該如何訪問呢?Struts2提供了一個特殊的OGNLPropertyAccessor,它可以自動查找棧內(nèi)的所有對象(從棧頂?shù)綏5?,直接找到一個具有你所查找的屬性的對象。也就是說,對于值棧中的任何對象都可以直接訪問,而不需要使用“#”?!   ?span id="d1pdr3b" class=Apple-converted-space> 
假設值棧中有兩個對象:student和employee,兩個對象都有name屬性,student有學號屬性number,而employee有薪水屬性salary。employee先入棧,student后入棧,位于棧頂,那么對于表達式name,訪問的就是student的name屬性,因為student對象位于棧頂;表達式salary,訪問的就是employee的salary屬性。正如你所見,訪問值棧中的對象屬性或方法,無須指明對象,也不用“#”,就好像值棧中的對象都是OGNL上下文中的根對象一樣。這就是Struts2在OGNL基礎上做出的改進。 

值棧中的Action實例   
Struts2框架總是把Action實例放在棧頂。因為Action在值棧中,而值棧又是OGNL中的根,所以引用Action的屬性可以省略“#”標記,這也是為什么我們在結果頁面中可以直接訪問Action的屬性的原因。 

Struts2中的命名對象     
Struts2還提供了一些命名對象,這些對象沒有保存在值棧中,而是保存在ActionContext中,因此訪問這些對象需要使用“#”標記。這些命名對象都是Map類型?!  ?span id="zdxfrrd" class=Apple-converted-space> 

parameters     
用于訪問請求參數(shù)。如:#parameters['id']或#parameters.id,相當于調(diào)用了HttpServletRequest對象的getParameter()方法?!   ?span id="xdpxfrj" class=Apple-converted-space> 
注意,parameters本質(zhì)上是一個使用HttpServletRequest對象中的請求參數(shù)構造的Map對象,一量對象被創(chuàng)建(在調(diào)用Action實例之前就已經(jīng)創(chuàng)建好了),它和HttpServletRequest對象就沒有了任何關系?!?span id="xlxtjjf" class=Apple-converted-space> 
   
request     
用于訪問請求屬性。如:#request['user']或#request.user,相當于調(diào)用了HttpServletRequest對象的getAttribute()方法?!  ?span id="xbbxblx" class=Apple-converted-space> 

session     
用于訪問session屬性。如:#session['user']或#session.user,相當于調(diào)用了HttpSession對象的getAttribute()方法。    

application     
用于訪問application屬性。如:#application['user']或#application.user,相當于調(diào)用了ServletContext的getAttribute()方法。    

attr     
如果PageContext可用,則訪問PageContext,否則依次搜索request、session和application對象。 

以下是轉過來的:先分清楚下ActionContext 、ValueStack 、Stack Context三者 

ActionContext 
一次Action調(diào)用都會創(chuàng)建一個ActionContext 
調(diào)用:ActionContext context = ActionContext.getContext() 

ValueStack 
由OGNL框架實現(xiàn) 
可以把它簡單的看作一個棧(List) 。 

Stack Object:放入stack中的對象,一般是action。 
Stack Context(map):stack上下文,它包含一系列對象,包括request/session/attr/application map等。 
EL:存取對象的任意屬性,調(diào)用對象的方法,遍歷整個對象結… 

ActionContext是Action上下文,可以得到request session application 
ValueStack是值棧 存放表單中的值 
Stack Context 棧上下文 也是用來存值的 



struts2對OGNL上下文的概念又做了進一步擴充,在struts2中,OGNL上下文通常如下所示: 

                        |--request   

                        |   

                        |--application   

                        |   

context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]   

                        |   

                        |--session   

                        |   

                        |--attr   

                        |   

                        |--parameters  




    在Struts2中,采用標準命名的上下文(Context)來處理OGNL表達式。處理OGNL的頂級對象是一個Map(也叫context map),而OGNL在這個context中就是一個頂級對象(root)。在用法上,頂級對象的屬性訪問,是不需要任何標記前綴的。而其它非頂級的對象訪問,需要使用#標記。 
    Struts2框架把OGNL Context設置為我們的ActionContext。并且ValueStack作為OGNL的根對象。除value stack之外,Struts2框架還把代表application、session、request這些對象的Map對象也放到ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的原因,他可以通過ActionContext對象來部分代替這些(Servlet API)功能,以方便對Action類進行測試?。?span id="fxbhhtv" class=Apple-converted-space> 
    Action的實例,總是放到value stack中。因為Action放在stack中,而stack是root(根對象),所以對Action中的屬性的訪問就可以省略#標記。但是,要訪問ActionContext中其它對象的屬性,就必須要帶上#標記,以便讓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。這個代碼在頁面上建立一個下拉選項,內(nèi)容是list中的內(nèi)容,默認值是name2. 
處理map 

<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" /> 

     需要注意的是,判斷一個值是否在collection中。我們要使用in或者not in來處理。 
<s:if test="'foo' in {'foo','bar'}"> 
   muhahaha 
</s:if> 
<s:else> 
   boo 
</s:else> 
另外,可以使用通配符來選擇collection對象的子集。 
——所有匹配選擇邏輯的元素 
^——只提取符合選擇邏輯的第一個元素 
$——只提取符合選擇邏輯的最后一個元素 
person.relatives.{? #this.gender == 'male'} 

````````````````````````````````````````````````````````````````````````````````` 

以下為補充摘錄的一些問題: 

提問:在Struts2中,如何使用自身的Tag讀取Action中的變量? 

Struts2自身的Tag會根據(jù)value中的OGNL表達式,在ValueStack中尋找相應的對象。因為action在ValueStack的頂部,所以默認情況下,Struts2的Tag中的OGNL表達式將查找action中的變量。請注意,value中的內(nèi)容直接是OGNL表達式,無需任何el的標簽包裝。 

例如:<s:property value="user.name" /> 

提問:在Struts2中,如何使用自身的Tag讀取HttpServletRequest,HttpSession中的變量? 

在上面的知識中,我們知道,Struts2中OGNL的上下文環(huán)境中,包含request,session,application等servlet對象的Map封裝。既然這些對象都在OGNL的上下文中,那么根據(jù)OGNL的基本知識,我們可以通過在表達式前面加上#符號來對這些變量的值進行訪問。 

例如:<s:property value="%{#application.myApplicationAttribute}" /> 
<s:property value="%{#session.mySessionAttribute}" /> 
<s:property value="%{#request.myRequestAttribute}" /> 
<s:property value="%{#parameters.myParameter}" /> 



提問:在Struts2中,如何使用JSTL來讀取Action中的變量? 

這是一個歷史悠久的問題。因為事實上,很多朋友(包括我在內(nèi))是不使用Struts2自身的標簽庫,而是使用JSTL的,可能因為JSTL標簽庫比較少,簡單易用的原因吧。 

我們知道,JSTL默認是從page,request,session,application這四個Scope逐次查找相應的EL表達式所對應的對象的值。那么如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行。所以,早在Webwork2.1.X的年代,我們會編寫一個攔截器來做這個事情的。大致的原理是:在Action執(zhí)行完返回之前,依次讀取Action中的所有的變量,并依次調(diào)用request.setAttribute()來進行設置。具體的整合方式,請參考以下這篇文檔:http://wiki./display/WW/Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1 

不過隨著時代的發(fā)展,上面的這種方式,已經(jīng)不再被推薦使用了。(雖然如此,我們依然可以學習它的一個解決問題的思路)目前來說,自從Webwork2.2以后,包括Struts2,都使用另外一種整合方式:對HttpServletRequest進行裝飾。讓我們來看一下源碼: 
Java代碼 
  1. public class StrutsRequestWrapper extends HttpServletRequestWrapper {     
  2.     
  3.     /**   
  4.      * The constructor   
  5.      * @param req The request   
  6.      */    
  7.     public StrutsRequestWrapper(HttpServletRequest req) {     
  8.         super(req);     
  9.     }     
  10.     
  11.     /**   
  12.      * Gets the object, looking in the value stack if not found   
  13.      *   
  14.      * @param s The attribute key   
  15.      */    
  16.     public Object getAttribute(String s) {     
  17.         if (s != null && s.startsWith("javax.servlet")) {     
  18.             // don't bother with the standard javax.servlet attributes, we can short-circuit this     
  19.             // see WW-953 and the forums post linked in that issue for more info     
  20.             return super.getAttribute(s);     
  21.         }     
  22.     
  23.         ActionContext ctx = ActionContext.getContext();     
  24.         Object attribute = super.getAttribute(s);     
  25.     
  26.         boolean alreadyIn = false;     
  27.         Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");     
  28.         if (b != null) {     
  29.             alreadyIn = b.booleanValue();     
  30.         }     
  31.     
  32.         // note: we don't let # come through or else a request for     
  33.         // #attr.foo or #request.foo could cause an endless loop     
  34.         if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {     
  35.             try {     
  36.                 // If not found, then try the ValueStack     
  37.                 ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);     
  38.                 ValueStack stack = ctx.getValueStack();     
  39.                 if (stack != null) {     
  40.                     attribute = stack.findValue(s);     
  41.                 }     
  42.             } finally {     
  43.                 ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);     
  44.             }     
  45.         }     
  46.         return attribute;     
  47.     }     
  48. }    

看到了嘛?這個類會在Struts2初始化的時候,替換HttpServletRequest,運行于整個Struts2的運行過程中,當我們試圖調(diào)用request.getAttribute()的時候,就會執(zhí)行上面的這個方法。(這是一個典型的裝飾器模式)在執(zhí)行上面的方法時,會首先調(diào)用HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會繼續(xù)到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達式,就能找到對應的值了。 

在這里,在el表達式廣泛使用的今天,JSTL1.1以后,也支持直接使用el表達式。注意與直接使用struts2的tag的區(qū)別,這里需要使用el的表示符號:${} 

例如:${user.name}, <c:out value="${department.name}" /> 

提問:在Struts2中,如何使用Freemarker等模板來讀取Action中的變量以及HttpServletRequest和HttpSession中的變量? 

Freemarker等模板在Struts2中有對應的Result,而在這些Result中,F(xiàn)reemarker等模板會根據(jù)ValueStack和ActionContext中的內(nèi)容,構造這些模板可識別的Model,從而使得模板可以以他們各自的語法對ValueStack和ActionContext中的內(nèi)容進行讀取。 

有關Freemarker對于變量的讀取,可以參考Struts2的官方文檔,非常詳細:http://struts./2.0.14/docs/freemarker.html 

設值計算 

Struts2中使用OGNL進行設值計算,就是指View層傳遞數(shù)據(jù)到Control層,并且能夠設置到相應的Java對象中。這個過程從邏輯上說需要分成兩步來完成: 

1. 對于每個請求,都建立一個與相應Action對應的ActionContext作為OGNL的上下文環(huán)境和ValueStack,并且把Action壓入ValueStack 

2. 在請求進入Action代碼前,通過某種通用的機制,搜集頁面上傳遞過來的參數(shù),并調(diào)用OGNL相關的代碼,對Action進行設值。 
上面的第一個步驟,在處理URL請求時完成,而第二個步驟由struts2內(nèi)置的攔截器完成。 






由于瀏覽了過多的文章,,具體的源地址未能記錄。。但還是感謝網(wǎng)上的原作者。。。 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲av日韩一区二区三区四区 | 国产日韩欧美一区二区| 在线亚洲成人中文字幕高清| 最近中文字幕高清中文字幕无 | 日韩女优精品一区二区三区| 免费观看一区二区三区黄片| 日本加勒比在线播放一区| 一二区不卡不卡在线观看| 在线观看中文字幕91| 黄男女激情一区二区三区| 亚洲一区二区三区日韩91| 中文久久乱码一区二区| 五月天丁香婷婷狠狠爱| 九九热精品视频在线观看| 国产亚州欧美一区二区| 香港国产三级久久精品三级| 国产精品欧美一级免费| 日本人妻熟女一区二区三区| 亚洲综合一区二区三区在线| 99久久精品午夜一区二区| 国产精品香蕉免费手机视频| 丝袜视频日本成人午夜视频| 久久国产青偷人人妻潘金莲| 国产精品偷拍视频一区| 色婷婷在线精品国自产拍| 又色又爽又无遮挡的视频| 91精品蜜臀一区二区三区| 中日韩免费一区二区三区| 大香蕉久久精品一区二区字幕| 办公室丝袜高跟秘书国产| 亚洲一区二区精品免费| 中文字幕久久精品亚洲乱码| 日韩欧美中文字幕av| 麻豆91成人国产在线观看| 亚洲免费黄色高清在线观看 | 91欧美一区二区三区| 免费观看日韩一级黄色大片| 亚洲最新中文字幕一区| 亚洲超碰成人天堂涩涩| 一区二区三区在线不卡免费| 亚洲综合色婷婷七月丁香|