struts2教程(9)--OGNL表达式使用
OGNL表示式使用和值棧
一、介紹
OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,它是一個開源項目。 Struts2框架使用OGNL作為默認的表達式語言。
? xwork 提供 OGNL表達式
? ognl-3.0.5.jar
OGNL 是一種比EL 強大很多倍的語言
?
OGNL 提供五大類功能
???1、支持對象方法調用,如xxx.doSomeSpecial();
???2、支持類靜態的方法調用和值訪問
???3、訪問OGNL上下文(OGNL context)和ActionContext; (重點 操作ValueStack值棧 )
???4、支持賦值操作和表達式串聯
???5、操作集合對象。
?
二、 使用OGNL訪問 對象方法 和 靜態方法
OGNL 在jsp 結合 struts2 標簽庫 使用 , <s:property value="ognl表達式" /> 執行 ognl表達式
調用 實例方法 : 對象.方法() ?---- ?<s:property value="'hello,world'.length()"/>
調用 靜態方法 : @[類全名(包括包路徑)]@[方法名] ?--- <s:property value="@java.lang.String@format('您好,%s','小明')"/>
使用 靜態方法調用 必須 設置 struts.ognl.allowStaticMethodAccess=true
?
三、 訪問OGNL上下文(OGNL context)和ActionContext
OGNL上下文(OGNL context) 對象 ----- 值棧 ValueStack
?
問題一 : 什么是值棧 ValueStack ?
ValueStack 是 struts2 提供一個接口,實現類 OgnlValueStack ---- 值棧對象 (OGNL是從值棧中獲取數據的 )
每個Action實例都有一個ValueStack對象 (一個請求 對應 一個ValueStack對象 )
在其中保存當前Action 對象和其他相關對象 (值棧中 是有Action 引用的 )
Struts 框架把 ValueStack 對象保存在名為 “struts.valueStack” 的請求屬性中,request中 (值棧對象 是 request一個屬性)
?
問題二 : 值棧的內部結構 ?
????值棧由兩部分組成
ObjectStack: Struts ?把動作和相關對象壓入 ObjectStack 中--List
ContextMap: Struts 把各種各樣的映射關系(一些 Map 類型的對象) 壓入 ContextMap 中
Struts 會把下面這些映射壓入 ContextMap 中
parameters: 該 Map 中包含當前請求的請求參數
request: 該 Map 中包含當前 request 對象中的所有屬性
session: 該 Map 中包含當前 session 對象中的所有屬性
application:該 Map 中包含當前 application ?對象中的所有屬性
attr: 該 Map 按如下順序來檢索某個屬性: request, session, application
?
ValueStack中 存在root屬性 (CompoundRoot) 、 context 屬性 (OgnlContext )
?? CompoundRoot 就是ArrayList
?? OgnlContext 就是 Map
?? context 對應Map 引入 root對象
?? context中還存在 request、 session、application、 attr、 parameters 對象引用
?? OGNL表達式,訪問root中數據時 不需要 #, 訪問 request、 session、application、 attr、 parameters 對象數據 必須寫 #
?? 操作值棧 默認指 操作 root 元素
?
問題三 : 值棧對象的創建 ,ValueStack 和 ActionContext 是什么關系 ?
值棧對象 是請求時 創建的
doFilter中 prepare.createActionContext(request, response);
創建ActionContext 對象過程中,創建 值棧對象ValueStack
ActionContext對象 對 ValueStack對象 有引用的 (在程序中 通過 ActionContext 獲得 值棧對象 )
Dispatcher類 serviceAction 方法中 將值棧對象保存到 request范圍
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
?
問題四 : 如何獲得值棧對象
獲得值棧對象 有兩種方法
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
問題五: 向值棧保存數據 (主要針對 root)
兩種方式
// 將數據保存root的索引0位置,放置到第一個元素 ArrayList add(0,element);
valueStack.push("itcast");
?
// 在值棧創建參數map, 將數據保存到map中
valueStack.set("company", "傳智播客");
在jsp中 通過 <s:debug /> 查看值棧的內容
?
問題六: 在JSP中獲取值棧的數據
????訪問root中數據 不需要#
????訪問 其它對象數據 加 #
通過下標獲取root中對象
???<s:property value="[0].top"/> //取值棧頂對象
直接在root中查找對象屬性 (自上而下自動查找)
??valueStack:<s:property value="username"/>
?
在OgnlContext中獲取數據
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>
四、 值棧在開發中應用
主流應用 : 值棧 解決 Action 向 JSP 傳遞 數據問題
?
Action 向JSP 傳遞數據處理結果 ,結果數據有兩種形式
1) 消息 String類型數據
this.addFieldError("msg", "字段錯誤信息");
this.addActionError("Action全局錯誤信息");
this.addActionMessage("Action的消息信息");
?
? fieldError 針對某一個字段錯誤信息 (常用于表單校驗)、actionError (普通錯誤信息,不針對某一個字段 登陸失敗)、 actionMessage 通用消息
?
在jsp中使用 struts2提供標簽 顯示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
2) 數據 (復雜類型數據)
使用值棧 ?valueStack.push(products);
?
哪些數據默認會放入到值棧?
1)每次請求,訪問Action對象 會被壓入值棧 ------- DefaultActionInvocation 的 init方法 stack.push(action);
??? Action如果想傳遞數據給 JSP,只有將數據保存到成員變量,并且提供get方法就可以了
2)ModelDriven 接口 有一個單獨攔截器
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
在攔截器中 ,將model對象 壓入了 值棧 stack.push(model);
?? 如果Action 實現ModelDriven接口,值棧默認棧頂對象 就是model對象
?
五、 值棧的數據 通過EL訪問
問題七:為什么 EL也能訪問值棧中的數據
?
StrutsPreparedAndExecuteFilter的doFilter代碼中 request = prepare.wrapRequest(request);
? 對Request對象進行了包裝 ,StrutsRequestWrapper
? 重寫request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
???attribute = stack.findValue(s);
}
??????訪問request范圍的數據時,如果數據找不到,去值棧中找
l?request對象 具備訪問值棧數據的能力 (查找root的數據)
?
?
六、 OGNL表達式 常見使用
#、 % 、$ 符號使用
1) # 的 使用
用法一 ?# 代表 ActionContext.getContext() 上下文
??<s:property value="#request.name" /> ?------------> ?ActionContext().getContext().getRequest().get("name");
??#request
??#session
??#application
??#attr
??#parameters
?
用法二 : 不寫# 默認在 值棧中root中進行查找
???<s:property value="name" /> 在root中查找name屬性
?查詢元素時,從root的棧頂元素 開始查找, 如果訪問指定棧中元素 ???<s:property value="[1].name" /> ?訪問棧中第二個元素name屬性
?訪問第二個元素對象 <s:property value="[1].top" />
?
用法三 :進行投影映射 (結合復雜對象遍歷 )
???1)集合的投影(只輸出部分屬性
????? <h1>遍歷集合只要name屬性</h1>
?????????
<s:iterator value="products.{name}" var="pname"><s:property value="#pname"/></s:iterator>???2)遍歷時,對數據設置條件
????? <h1>遍歷集合只要price大于1500商品</h1>
????????
<s:iterator value="products.{?#this.price>1500}" var="product"><s:property value="#product.name"/> --- <s:property value="#product.price"/></s:iterator>???3)綜合
???<h1>只顯示價格大于1500 商品名稱</h1>
<s:iterator value="products.{?#this.price>1500}.{name}" var="pname"> <s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/></s:iterator><s:property value="#pname"/></s:iterator>
?
用法四: 使用#構造map集合
經常結合 struts2 標簽用來生成 select、checkbox、radio
<h1>使用#構造map集合 遍歷</h1>
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/></s:iterator>?
2) %的使用
???用法一:?結合struts2 表單表單使用, 通過%通知struts, %{}中內容是一個OGNL表達式,進行解析
???<s:textfield name="username" value="%{#request.username}"/>
???用法二:?設置ognl表達式不解析 %{'ognl表達式'}
???<s:property value="%{'#request.username'}"/>
?
3)$的使用
???用法一 :用于在國際化資源文件中,引用OGNL表達式
???????????????? 在properties文件 msg=歡迎您, ${#request.username}
???用法二?:在Struts 2配置文件中,引用OGNL表達式
?????????????? <!-- 在Action 提供 getContentType方法 -->
?????????????? <param name="contentType">${contentType}</param>
????? ${contentType} 讀取值棧中contentType數據,在Action提供 getContentType 因為Action對象會被壓入值棧,
??????contentType是Action屬性,從值棧獲得
?
結論: #使用ognl表達式獲取數據,% 控制ognl表達式是否解析 ,$ 用于配置文件獲取值棧的數據
總結
以上是生活随笔為你收集整理的struts2教程(9)--OGNL表达式使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: struts2教程--实现文件上传下载
- 下一篇: struts2教程(10)