day33Struts2Day03(OGNL表示式、值棧)
阿新 • • 發佈:2018-11-29
回顧 1、Servlet的API ActionContext物件 ServletActionContext物件 2、結構型別的跳轉 全域性結果 區域性結構 type屬性 3、資料的封裝 屬性驅動方式 模型驅動方式 實現ModelDrivern 介面 4、攔截器(自定義攔截器) OGNL表示式概述 1、OGNL是Object Navigation Language(物件圖導航語言) 所謂物件圖,即以任意一個物件為根,通過OGNL可以訪問與這個物件關聯的其他物件 通過它簡單一致的表示式語法,可以存取物件的任意屬性,呼叫物件的方法,遍歷整個物件的結構圖,實現欄位型別轉換等功能。使用相同的表示式去存取物件的屬性 2、Struts2框架使用OGNL作為預設的表示式語言 OGNL是一種比EL強大很多倍的語言 xwork提供OGNL表示式 ognl-3.0.5.jar 3、OGNL提供五大類功能 支援物件方法呼叫 支援類靜態的方法呼叫和值訪問 訪問OGNL上下文(OGNL context)和ActionContext 支援賦值操作和表示式串聯 操作集合物件 1、什麼是值棧 值棧就相當於Struts2框架的資料的中轉站,向值棧存入一些資料,從值棧中獲取到資料 ValueStack 是Struts2提供一個介面,實現類OgnlValueStack--值棧物件(OGNL是從值棧中獲取資料的) Action是多例的,有一起請求,建立Action例項,建立一個ActionContext物件,代表的是Action的上下文物件,還會建立一個ValueStack物件 每個Action例項都有一個ValueStack物件(一個請求,對應一個ValueStack物件) 在其中儲存當前Action物件和其他相關物件 Struts框架把ValueStack物件儲存在名為“struts.valueStack”的請求屬性中,request中(值棧物件是request一個屬性) ValueStack vs = (ValueStack)request.getAttribute("struts.valueStack"); 2、值棧的內部結構 值棧由兩部分組成 root Struts把動作和相關物件壓入ObjectStack中--List context Struts把各種各樣的對映關係(一些Map型別的物件)壓入ContextMap中 Struts會預設把下面這些對映壓入ContextMap(Context)中 request代表的是Map集合的key值,value值其實也是一個Map值 parameters:該Map中包含當前請求的請求引數?name=xxx&password=123 request:該Map中包含當前request物件中的所有屬性 session:該Map中包含當前session物件中的所有屬性 application:該Map中包含當前application物件中的所有屬性 attr:該Map按如下順序來檢索某個屬性:request、session、application ValueStack存在root屬性(CompoundRoot)context屬性(OgnlContext)、 CompoundText就是ArrayList OgnlContext就是Map context對應Map引入root物件 context中還存在request、session、application、attr、parameters物件引用 OGNL表示式訪問值棧中的資料 訪問root中資料時,不需要# 訪問request、session、application、attr、parameters物件資料必須寫# 操作值棧預設指操作root元素 3、值棧物件的建立,ValueStack和ActionContext是什麼關係 值棧物件是請求時建立的 ActionContext是繫結到當前的執行緒上,那麼在每個攔截器或者Action中獲取的ActionContext是同一個 ActionContext中存在一個Map集合,該Map集合和ValueStack的contextMap是同一個地址 ActionContext中可以獲取到ValueStack的引用 4、獲取值棧物件 (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack"); (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); ActionContext.getContext().getValueStack(); 5、向值棧儲存資料(主要針對root棧) valueStack.push(Object obj) push方法的底層呼叫root物件的push方法(把元素新增到0位置) valueStack.set(String key,Object obj) 原始碼獲取map集合(map可能是已經存在的,有可能是新建立的)把map集合push到棧頂,再把資料存入到map集合中 在jsp中通過<s:debug/>檢視值棧的內容 6、從值棧中獲取值 訪問root中資料 不需要# 訪問context其他物件資料 加# 如果向root中存入物件的話 優先使用push方法 如果向root中存入集合的話,優先要使用set方法 在OGNLContext中獲取資料 在Action中向與物件中存入值 xxxx:<s:property value="#xxxx.屬性"/> request、session、application、attr、parameters 7、獲取到值棧中的資料 為什麼EL也能訪問值棧中的資料 StrutsPreparedAndExecuteFilter的doFilter程式碼中 request = prepare.wrapRequest(request) 對request物件進行了保證,StrutsRequestWrapper org.apache.struts2.dispatcher.StrutsRequestWrapper 增強了request的getAttribute Object attribute = super.getAttribute(key); if (ctx != null && attribute == null) { boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE)); // note: we don't let # come through or else a request for // #attr.foo or #request.foo could cause an endless loop if (!alreadyIn && !key.contains("#")) { try { // If not found, then try the ValueStack ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE); ValueStack stack = ctx.getValueStack(); if (stack != null) { attribute = stack.findValue(key); } } finally { ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE); } } 訪問request範圍的資料時,如果資料找不到,在值棧中找 request物件 具備訪問值棧資料的能力(查詢root的資料) OGNL的特殊符號 1、#符號的用法 獲取contextMap中的資料 <s:property value="#xxxx.屬性"/> request/session/application/attr/parameters 構建一個集合 性別<s:radio name="sex" list="{'男','女'}"></s:radio> 性別<s:radio name="sex" list="#{'1':'男','2':'女'}"></s:radio> 2、%符號的用法 強制字串解析成OGNL表示式 例如:在request域中存入值,然後在文字框(<s:textfield>)中取值,現在到value上 <s:textfield value="%{#request.msg}"/> {}中值用''引起來,此時不再是ognl表示式,而是普通的字串 <s:property value="%{'#request.msg'}"/> <s:property value="'aaa'"/> 3、$符號的用法 在配置檔案中可以使用OGNL表示式,例如:檔案下載的配置檔案 <action name="download" class="my.demo2.DownLoadAction"> <result> <param name="contentType">${contentType}</param> <param name="contentDisposition">attachment:filename=${downFilename}</param> </result> </action>