1.OGNL 出現的意義
? ?在mvc中,數據是在各個層次之間進行流轉是一個不爭的事實。而這種流轉,也就會面臨一些困境,這些困境,是由于數據在不同世界中的表現形式不同而造成的:
a. 數據在頁面上是一個扁平的,不帶數據類型的字符串,無論你的數據結構有多復雜,數據類型有多豐富,到了展示的時候,全都一視同仁的成為字符串在頁面上展現出來。
b. 數據在Java世界中可以表現為豐富的數據結構和數據類型,你可以自行定義你喜歡的類,在類與類之間進行繼承、嵌套。我們通常會把這種模型稱之為復雜的對象樹。此時,如果數據在頁面和Java世界中互相流轉傳遞,就會顯得不匹配。所以也就引出了幾個需要解決的問題;
c. 當數據從View層傳遞到Controller層時,我們應該保證一個扁平而分散在各處的數據集合能以一定的規則設置到Java世界中的對象樹中去。同時,能夠聰明的進行由字符串類型到Java中各個類型的轉化;
d. 當數據從Controller層傳遞到View層時,我們應該保證在View層能夠以某些簡易的規則對對象樹進行訪問。同時,在一定程度上控制對象樹中的數據的顯示格式。
? ? ?如果我們稍微深入一些來思考這個問題,我們就會發現,解決數據由于表現形式的不同而發生流轉不匹配的問題對我們來說其實并不陌生。同樣的問題會發生在Java世界與數據庫世界中,面對這種對象與關系模型的不匹配,我們采用的 解決方法是使用ORM框架,例如Hibernate,iBatis等等。那么現在,在Web層同樣也發生了不匹配,所以我們也需要使用一些工具來幫助我們解決問題。為了解決數據從View層傳遞到Controller層時的不匹配性,Struts2采納XWork ? ? 的一套完美方案。并且在此的基礎上,構建了一個完美的機制,從而比較完美的解決了數據流轉中的不匹配性。OGNL方案就應運而生
2.OGNL項目實戰
? ?OGNL是Object-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言,通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,
遍歷整個對象的結構圖,實現字段類型轉化等功能。
a. OGNL可以讓我們用非常簡單的表達式訪問對象層【OGNL支持對Map的按鍵值查找】
<ww:property value='user.name' /> 可以直接點對象的屬性,如user 屬性是list,<ww:property value='user[0].name' /> 可以獲取第一個user對象的 name如user 屬性是一個 map <ww:property value='user[name]' /> 獲取user "name" key 對應的 value
b. 支持運算符(如+-*/),比普通的標志具有更高的自由度和更強的功能
<ww:property value="100 - wcjd"/>
c. 支持對象方法調用,如xxx.doSomeSpecial()
d. 支持類靜態的方法調用和值訪問,表達式的格式為@[類全名(包括包路徑)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME
<ww:property value="#DateUtil.getNowdate(\"yyyy-MM-dd\")"/>
e. 支持賦值操作和表達式串聯,如price=100, discount=0.8, calculatePrice(price*discount),這個表達式會返回80
f .訪問OGNL上下文(OGNL context)和ActionContext
g.你也可以通過任意類對象的構造函數進行對象新建
/** new Java.net.URL("xxxxxx/") **/
h.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的列表 **/
i. OGNL是通常要結合Struts 2的標志一起使用,主要是#、%和$這三個符號的使用。使用方法如下:
/** 訪問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'}。%”符號的用途是在標志的屬性為字符串類型時,計算OGNL表達式的值。“$”有兩個主要的用途,用于在國際化資源文件中,引用OGNL表達式。在Struts 2和i18n中配置文件/**
j. OGNL 可以獲取后臺 action get()set() 方法 傳送過來的數據靈活展示到前臺