下午對這個地方一直感覺很模糊……然後“決心”查一查,查了之後還是有效果的!嘿嘿……野豬,加油!野豬記住!你是一隻野豬,現在是,将來也是!要學會獨立!嘿嘿……說正題吧……
一、"#"的用法
1、 通路OGNL上下文和Action上下文,#相當于ActionContext.getContext();下表有幾個ActionContext中有用的屬性:
parameters 包含目前HTTP請求參數的Map #parameters.id[0]作用相當于request.getParameter("id")
request 包含目前HttpServletRequest的屬性(attribute)的Map #request.userName相當于request.getAttribute("userName")
session 包含目前HttpSession的屬性(attribute)的Map #session.userName相當于session.getAttribute("userName")
application 包含目前應用的ServletContext的屬性(attribute)的Map #application.userName相當于application.getAttribute("userName")
attr 用于按request > session > application順序通路其屬性(attribute) #attr.userName相當于按順序在以上三個範圍(scope)内讀取userName屬性,直到找到為止
2、用于過濾和投影(projecting)集合,如books.{?#this.price<100};
3、構造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
二、"%"的用法
“%”符号的用途是在标志的屬性為字元串類型時,計算OGNL表達式的值。例如在Ognl.jsp中加入以下代碼:
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
三、"$"的用法
1、用于在國際化資源檔案中,引用OGNL表達式
2、在Struts 2配置檔案中,引用OGNL表達式
例如:
<action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action? albumId=${albumId}</result>
</action>
struts2中的OGNL上下文
struts2對OGNL上下文的概念又做了進一步擴充,在struts2中,OGNL上下文通常如下所示:
|–request
|
|–application
context map—|–OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|–session
|–attr
|–parameters
我們可以使用”#requet”通路HttpServletRequest對象, “#session”通路HttpSession對象,但請注意”根對象”是什麼?是ValueStack!
那麼ValueStack是什麼?值棧。也就是一組對象的堆棧。也就是說,在struts2中,根對象不是我們通常的一個對象,而是一組對象。我們可以 push新的對象到值棧中,也可以彈出值棧的棧頂對象。如上圖所示,假設我們将user對象push到值棧中,那麼如下的表達式将與之前我們見過的表達式一樣,具有相同的結果:
Java代碼
name // 取使用者的姓名
age // 取使用者年齡
birthday // 取使用者生日
customer.name // 取使用者所屬客戶的名稱
#request.parameters // 取請求參數
也就是說,我們使用name這個表達式的時候,ONGL會取”根對象”的name屬性,但現在根對象是ValueStack!那麼通路 ValueStack的name屬性意味着什麼呢?這意味着: ValueStack會先檢視棧頂元素是否有name屬性,如果有就傳回該屬性值,否則取出棧頂下的元素,繼續檢視,直到棧底為止。
關于ValueStack
Struts2的Action類通過屬性可以或得所有相關的值,如請求參數、action配置參數、向其他Action傳遞屬性值(通過Chain結果)等等。
要獲得這些參數值,我們要做的唯一一件事就是在Action類中聲明與參數同名的屬性,在Struts2調用Action類的Action方法之前,就會為相應的Action屬性指派,要完成這個功能,有很大程度上,Struts2要依賴ValueStack對象。這個對象貫穿整個Action的生命周期(每個Action類的對象執行個體會擁有一個ValueStack對象)。當Struts2接收到一個.action的請求後,會先建立Action類的對象執行個體,但并不會調用Action方法,而是先将Action類的相應屬性放到ValueStack對象的頂層節點(ValueStack對象相當于一個棧)。隻是所有的屬性值都是預設的值,如String類型的屬性值為null,int類型的屬性值為0等。處理完上述工作後,Struts2就會調用攔截器鍊中的攔截器,當調用完所有的攔截器後,最後會調用Action類的Action方法,在調用Action方法之前,會将ValueStack對象頂層節點中的屬性值賦給Action類中相應的屬性,注意,在這裡就給我們呆了很大的靈活性。也就是說,在Struts2調用攔截器的過程中,可以改變ValueStack對象中屬性的值,當改變某個屬性之後,Action類的相應屬性值就會變成在攔截器中最後改變該屬性的這個值。
從上面的描述很容易知道,在Struts2的Action類可以獲得與屬性同名的參數值就是通過不同的攔截器來處理的,如獲得請求參數的攔截器是params,獲得Action的配置參數的攔截器是staticParams等,在這些攔截器内部讀取相應的值,并更新ValueStack對象頂層節點的相應屬性的值。而ValueStack對象就像一個傳送帶,将屬性的值從一個攔截器傳到了另一個攔截器(當然,在這期間,屬性值可能改變),最後會傳到Action對象,并将ValueStack對象中的屬性的值的終值賦給Action類的相應屬性。