1. 表達式語言OGNL OGNL簡介 OGNL基本語法 常量 操作符 OGNL表達式 OGNL基礎 OGNL上下文 OGNL值棧 OGNL的訪問 常量 操作符 OGNL表達式 OGNL上下文 OGNL值棧 OGNL的訪問 2. 具體內容 2.1 OGNL簡介 OGNL(Object-Graph N ...
1. 表達式語言OGNL
- OGNL簡介
- OGNL基本語法
- 常量
- 操作符
- OGNL表達式
- OGNL基礎
- OGNL上下文
- OGNL值棧
- OGNL的訪問
2. 具體內容
2.1 OGNL簡介
OGNL(Object-Graph Navigation Language)對象圖導航語言的縮寫,OGNL是一種表達式語言(Expression Language, EL)。可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現欄位類型轉化等功能。
OGNL是一種對java對象的getter和setter屬性的表示和綁定語言。通常,OGNL使用簡單一致的表達式語法去存取對象的屬性。
2.2 OGNL基本語法
2.2.1 常量
- 字元串常量:以單引號或雙引號括起來的字元串。支持轉義字元"\";
- 字元常量:以單引號括起來的字元,例如'C';
- 數值常量:java中的int、long、float和double;
- 布爾常量:true和false;
- null常量。
JSP頁面中輸出常量的示例代碼如下:
<%@ taglib prefix="s" uri="/struts-tags" %> <!--加入Struts2的標簽庫--> <s:property value = "'you said,\"Hello World\".'"/><br> <s:property value = "true"/><br> <s:property value = "null"/><br> <s:property value = "12.3f"/>
2.2.2 操作符
OGNL的逗號支持所有的Java操作符(+、-、*、/、++、--、!=、==、=等)與java類似還提供了一些特有的操作符號。下麵介紹OGNL的一些特有的操作符號。
1. 逗號(,)或序列操作符
逗號被用來分隔兩個或者多個獨立的表達式,整個表達式的值是最後一個表達式的值;例如:
team1.person.name, team2.teamname;
整個表達式的值是第二個表達式的值。
2. 大括弧操作符{};
大括弧操作符用於創建表(數組)。使用大括弧將元素括起來,元素之間使用逗號分隔開。例如:
{"mayun","liyanhong","mahuateng"}[1];
此表達式創建了一個帶有三個元素的列表,並且訪問其中第二個元素,在JSP頁面中輸出第二個元素值的代碼如下:
<s:property value="{'mayun','liyanhong','mahuateng'}[1]"/>
3. in和not in的操作符
in和not in用來判斷一個值是否屬於一個集合中。例如:
teamname in {'team1','team2'};
此表達式判斷teamname是否在數組{'team1','team2'}中,在返回true,不在返回false。
2.2.3 OGNL表達式
使用OGNL表達式可以訪問屬性、方法、靜態屬性和方法、構造方法、數組以及集合等。
1. 訪問屬性
OGNL訪問屬性示例代碼如下:
<!--訪問屬性--> <s:property value = "uname"/>
<!--訪問對象屬性(get和set)--> <s:property value = "user.age"/> <s:property value = "employee.manager.uname"/>
2. 訪問方法
OGNL訪問方法示例代碼如下:
<!--訪問對象的方法--> <s:property value = "employee.eat()"/> <!--訪問action的方法--> <s:property value = "add()"/>
3. 訪問靜態屬性和方法
OGNL支持調用類中的靜態方法和靜態欄位,可以使用如下語法格式:@class@method(args);@class@field;其中,class必須給出完整的類名,如@java.lang.String@valueOf(5)。如果省略class,則預設使用類java.lang.Math。示例代碼如下:
<!--訪問靜態方法--> <s:property value = "@com.my.ognl.StaticSample@ma()"/> <!--訪問靜態屬性--> <s:property value = "@com.my.ognl.StaticSample@STR"/> <!--訪問Math的靜態方法--> <s:property value = "@@max(4,7)"/>
需要註意的是,在配置文件(Struts.xml)中,添加如下常量(夾在<struts>標簽中,<package>標簽上方),OGNL才能訪問靜態屬性和方法:
<constant name = "Struts.ognl.allowStaticMethodAccess" value = "true"/>
如下圖所示:
4. 訪問構造方法
OGNL訪問構造方法的示例代碼如下:
<!--訪問構造方法--> <s:property value = "new com.my.org.User(44)"/>
5. 訪問集合和數值
可以使用OGNL語言直接生成集合元素(如List對象或Map對象);利用下式代碼可以直接生成一個List對象:
{e1,e2,e3};
可以使用如下代碼直接生成一個Map對象:
# {key1:value1 , key2:value2 , key3:value3};
Map集合對象,使用key-value格式定義,每個key-value元素使用冒號標識,多個元素之間採用逗號隔開。對於集合類型OGNL可以使用in和not in兩個元素符號,判斷元素是否在指定的集合內。
需要註意的是,OGNL能夠引用集合的一些特殊的屬性,這些屬性不是JavaBeans模式,如size。當表達式引用這些屬性時, OGNL 會調用相應的方法,這就是偽屬性。
OGNL中特殊的集合偽書性如下表所示:
集合類型 | 偽屬性 | OGNL表達式 | Java代碼 |
List,Set,Map | size;isEmpty | list.size;set.isEmpty | list.size();set.isEmpty |
List,Set | iterator | list.iterator;set.iterator | list.iterator();set.iterator() |
Map | keys,values | map.keys;map.values | map.keySet();map.values() |
Iterator | next,hasNext | it.next;it.hasNext | it.next();it.hasNext() |
6. 投影
OGNL中提供了一種簡單的方式在一個集合中對每一個元素調用相同的方法,或抽取相同的屬性,並將結果保存為一個新的集合,稱為投影。
假設employees是一個包含了employee對象的列表,那麼:
# employees.{name} // 表示返回所有雇員的名字的列表
在投影期間,使用 # this變數來引用迭代中的當前元素。例如:
Object.{#this instanceof String? #this: #this.toString()}
7. 選擇
OGNL提供了一種簡單的方式來使用表達式從集合中選擇某些元素,並將結果保存到新的集合中,稱為選擇。其中選擇表達式中的關於選擇的特殊字元說明如下:
- ?:選取匹配邏輯的所有元素;
- ^:選取匹配選擇邏輯的第一個元素;
- $:選取匹配的最後一個元素;
示例代碼如下:
<!--將返回薪水大於3000雇員的列表--> # employees.{?#this.salary > 3000}
<!--將返回第一個薪水大於3000的雇員--> # employees.{^#this.salary > 3000}
<!--將返回最後一個薪水大於3000的雇員--> # employees.{$#this.salary > 3000}
8. OGNL表達式符號
在Struts2 OGNL中的#和%符號用法說明如下:
(1) #符號
- 訪問非根對象屬性,如 #session.msg表達式,# 相當於ActionContext.getContext();
- 用於選擇和投影集合,如person.{?#this.age>30};
- 用來構造Map集合,如 #{0:男,1:女}
(2) %符號
%符號的用途是,在標誌的屬性為字元串類型時,計算OGNL表達式的值。例如,下麵的代碼所示:
<s:set name = "foobar" value="# {'foo1':'bar','foo2':'bar2'}"/> <s:url value="%{#foobar['fool']}"/>
2.3 OGNL基礎
2.3.1 OGNL上下文
OGNL的計算都是圍繞上下文進行的,OGNL上下文實際上就是一個Map對象,由ognl.OgnlContext類(實現了java. util. Map介面)來表示。
Struts2將OGNLContext設置為ActionContext,即在Struts2中OGNL上下文(Context)的實現為ActionContext。Struts2將ValueStack(值棧)作為OGNL的根對象。
當Struts2接受一個請求時,會迅速創建ActionContext(上下文),ValueStack(值棧),action。然後把action存進ValueStack,所以action的實例變數可以被OGNL訪問。在Struts2中,OGNL表達式需要配合Struts2標簽才可以使用,如下所示:
<s:property value = "uname"/>
2.3.2 值棧
值棧作為OGNL的根對象(root對象),類似於正常的棧,符合”後進先出“的特點,可以在值棧中放入、刪除、查詢對象,值棧是Struts2的核心。
如果要訪問根對象(即ValueStack)中的對象的屬性,則可以省略 # 命名空間,直接訪問該對象的屬性既可。如下,讀取棧中的數據。
<!--按照後進先出的方式,讀取棧中元素--> <s:property value="#root[0].loginname"/> <s:property value="#root[1].loginname"/> <s:property value="#root[2].loginname"/>
2.3.3 OGNL的訪問
由於ValueStack是Struts2中的OGNL的根對象。如果用戶需要訪問值棧中的對象,在JSP頁面可以通過輸入如下表達式語言(EL)訪問ValueStack中對象的屬性:
<!--獲得值棧中某個對象的foo屬性--> $ {foo} <!--也可以通過Struts標簽訪問ValueStack中的對象--> <s:property value="foo"/>
如果訪問其他Context中的對象,由於它們不是根對象,所以在訪問時,需要添加 # 首碼。具體如下:
- application對象:用於訪問ServletContext,如 # application.userName 或者 # application['userName'],相當於調用了ServletContext 的 getAttribute("username");
- session對象:用來訪問HttpSession,如 # session.userName 或者 # session['userName'],相當於調用了session .getAttribute('userName');
- request對象:用來訪問HttpServletRequest屬性的Map,如 # request.userName 或者 # request['userName'],相當於調用request.getAttribute("userName");
- parameters對象:用來訪問HTTP的請求參數,如 # parameters.userName 或者 # parameters['userName'],相當於調用 requst.getParameter("userName")。