OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,經過它簡單一致的表達式語法,能夠存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的
表達式去存取對象的屬性。
基本介紹
OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,經過它簡單一致的表達式語法,能夠存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖, 實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。這樣能夠更好的取得數據。
OGNL可讓咱們用很是簡單的表達式訪問對象層,例如,當前環境的根對象爲user1,則表達式person.address[0].province能夠訪問到user1的person屬性的第一個address的province屬性。
這種功能是模板語言的一個重要補充,象jsp2.0,velocity,jelly等等,都有相似的功能,可是ognl比它們完善得多,並且以一個獨立的lib出現,方便咱們構建本身的框架。
webwork2和如今的
Struts2.x中使用OGNL取代原來的EL來作界面數據綁定,所謂界面數據綁定,也就是把界面元素(例如一個textfield,hidden)和對象層某個類的某個屬性綁定在一塊兒,修改和顯示自動同步。
和
struts1.x的formbean相比,這樣作的好處很是明顯:在
webwork中 不須要爲每一個頁面專門寫formbean,能夠直接利用對象層的對象。例如在對象設計中,咱們的User和Person是分開的,而一個註冊用戶界面須要 填寫二者的內容,在webwork中,就能夠保持後臺的對象結構,把屬於用戶屬性的界面元素用user.person.xxx綁定,把屬於帳號屬性的界面 元素用user.xxx綁定。
Struts 2
OGNL(Object-Graph Navigation Language),能夠方便地操做對象屬性的開源
表達式語言,使頁面更簡潔;
支持
運算符(如+-*/),比普通的標誌具備更高的自由度和更強的功能;
Struts 2默認的表達式語言是OGNL,緣由是它相對其它表達式語言具備下面幾大優點:
支持對象方法調用,如xxx.doSomeSpecial();
支持類靜態的方法調用和值訪問,表達式的格式爲@[類全名(包括包路徑)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
支持賦值操做和
表達式串聯,如price=100, discount=0.8, calculatePrice(price*discount),這個表達式會返回80;
訪問OGNL上下文(OGNL context)和ActionContext;
操做集合對象。
能夠直接new一個對象
用法
OGNL是一般要結合Struts 2的標誌一塊兒使用。主要是#、%和$這三個符號的使用。使用方法以下:
新建名爲Struts2_OGNL的Web工程
#」主要有三種用途:
訪問OGNL上下文和Action上下文,#至關於ActionContext.getContext();下表有幾個ActionContext中有用的屬性: 名稱 做用 例子
parameters 包含當前
HTTP請求參數的Map #parameters.id[0]做用至關於request.getParameterValues("id").get(0);
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屬性,直到找到爲止
用於過濾和投影(projecting)集合,如books.{?#this.price<100};
構造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
下面讓咱們它們的具體寫法,首先是Action類代碼:
package tutorial.action;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.
struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;
import tutorial.model.Book;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction extends ActionSupport implements ServletRequestAware, SessionAware, ServletContextAware {
private static final long serialVersionUID = 1L;
private HttpServletRequest request;
private Map session;
private ServletContext application;
private List books;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@SuppressWarnings("unchecked")
public void setSession(Map session) {
this.session = session;
}
public void setServletContext(ServletContext application) {
this.application = application;
}
public List getBooks() {
return books;
}
@Override
public String execute() {
request.setAttribute("userName", "Max From request");
session.put("userName", "Max From session");
application.setAttribute("userName", "Max From application");
books = new LinkedList();
books.add(new Book("978 0735619678", "Code Complete, Second Edition", 32.99));
books.add(new Book("978 0596007867", "The Art of Project Management", 35.96));
books.add(new Book("978 0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));
books.add(new Book("978 0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));
books.add(new Book("978 0735605350", "Software Estimation: Demystifying the Black Art", 25.19));
return SUCCESS;
}
}
以上代碼分別在request、session和application的範圍內添加「userName」屬性,而後再在JSP頁面使用OGNL將其取回。
下面是Ognl.jsp的代碼,內容以下:
訪問OGNL上下文和Action上下文
parameters.userName:
request.userName:
session.userName:
application.userName:
attr.userName:
用於過濾和投影(projecting)集合
Books more than $35
<s:iterator value="books.{?#this.price > 35}">
<s:property value="title" /> - $<s:property value="price" /><br>
</s:iterator>
The price of "Code Complete, Second Edition" is:
構造Map
The value of key "foo1" is
清單3 WebContent/Ognl.jsp 以上代碼值得注意的是「」,由於「books.{?#this.title=='Code Complete, Second Edition'}.{price}」返回的值是集合類型,因此要用「[索引]」來訪問其值。 最後是Struts 2的配置文件
struts.xml,內容以下:
/Ognl.jsp
「%」符號的用途是在標誌的屬性爲字符串類型時,計算OGNL
表達式的值。
「$」有兩個主要的用途,用於在國際化資源文件中,引用OGNL表達式。在Struts 2和i18n中配置文件
由來
OGNL stands for Object-Graph Navigation Language; it is an expression language for getting and setting properties of Java objects. You use the same expression for both getting and setting the value of a property.
The ognl.Ognl class contains convenience methods for evaluating OGNL expressions. You can do this in two stages, parsing an expression into an internal form and then using that internal form to either set or get the value of a property; or you can do it in a single stage, and get or set a property using the String form of the expression directly.
OGNL started out as a way to set up associations between UI components and controllers using property names. As the desire for more complicated associations grew, Drew Davidson created what he called KVCL, for Key-Value Coding Language, egged on by Luke Blanshard. Luke then reimplemented the language using ANTLR, came up with the new name, and, egged on by Drew, filled it out to its current state. Later on Luke again reimplemented the language using JavaCC. Further maintenance on all the code is done by Drew (with spiritual guidance from Luke).
表達式
OGNL支持各類紛繁複雜的表達式。可是最最基本的表達式的原型,是將對 象的引用值用點串聯起來,從左到右,每一次表達式計算返回的結果成爲當前對象,後面部分接着在當前對象上進行計算,一直到所有表達式計算完成,返回最後得 到的對象。OGNL則針對這條基本原則進行不斷的擴充,從而使之支持對象樹、
數組、容器的訪問,甚至是相似SQL中的投影選擇等操做。
1. 基本對象樹的訪問
對象樹的訪問就是經過使用點號將對象的引用串聯起來進行。
例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx
2. 對容器變量的訪問
例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx
3. 使用操做符號
OGNL表達式中能使用的操做符基本跟Java裏的操做符同樣,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操做符以外,還能使用 mod, in, not in等。
OGNL支持對數組和ArrayList等容器的順序訪問:例如:group.users[0]
同時,OGNL支持對Map的按鍵值查找:
例如:#session['mySessionPropKey']
例如:{"green", "red", "blue"}構造一個List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}構造一個Map
例如:new Java.net.URL("xxxxxx/")
要引用類的靜態方法和字段,他們的表達方式是同樣的@class@member或者@class@method(args):
例如:@com.javaeye.core.Resource@ENABLE,@com.javaeye.core.Resource@getAllResources
6. 方法調用
直接經過相似Java的方法調用方式進行,你甚至能夠傳遞參數:
例如:user.getName(),group.users.size(),group.containsUser(#requestUser)
7. 投影和選擇
OGNL支持相似數據庫中的投影(projection) 和選擇(selection)。
投影就是選出集合中每一個元素的相同屬性組成新的集合,相似於關係數據庫的字段操做。投影操做語法爲 collection.{XXX},其中XXX 是這個集合中每一個元素的公共屬性。
例如:group.userList.{username}將得到某個group中的全部user的name的列表。
選擇就是過濾知足selection 條件的集合元素,相似於關係數據庫的紀錄操做。選擇操做的語法爲:collection.{X YYY},其中X 是一個選擇操做符,後面則是選擇用的
邏輯表達式。而選擇操做符有三種:
? 選擇知足條件的全部元素
^ 選擇知足條件的第一個元素
$ 選擇知足條件的最後一個元素
例如:group.userList.{? #txxx.xxx != null}將得到某個group中user的name不爲空的user的列表。