struts2-OGNL基礎
OGNL(Object-Graph Navigation Language)是一種強大的表示式語言,是一個第三方開源專案。
OGNL本身是與struts2 沒有任何關係 ,但struts2框架使用了OGNL用於進行表示式的計算工作。struts2通過使用OGNL簡單一致的表示式語法,可以存取物件的任意屬性,呼叫物件的方法,遍歷整個物件的結構圖,實現欄位型別轉換等功能。
OGNL特點:
- 支援物件方法呼叫
- 可以操作集合物件
- 可以直接建立物件
- 支援類靜態方法呼叫和常量訪問,表示式的格式為:
@[全限定性類名]@[方法名|常量名]
如:@[email protected]
不過靜態方法的訪問,需要通過在struts2的配置檔案struts.xml中設定常量struts.ognl.allowStaticMethodAccess的值為true進行開啟。
OGNL以map的形式展現其內部(文件原句:The top level object dealing with OGNL is a Map (usually referred as a context map or context))
在action中直接獲取context及內部的值很麻煩,所以給了context另一個定義,即ActionContext。可以通過ActionContext簡單獲取。(servletApi值也是存在這裡,所以獲取的也是這裡面的,所以ActionContext.getContext獲取的不是真正的request)
ValueStack vs = ActionContext.getContext().getValueStack();//獲取值棧
OGNL中的值棧是核心,對其操作方式有如下:(對值棧操作實質上是對其中的root進行操作)
//向值棧中加入無名物件,實際是放到它的root屬性中
Student st= new Student("zhangsan",21);
vs.push(st);
//向值棧直接放入有名物件,實際是放到它的root屬性中
Student st1 = new Student("lisi" ,20);
Map<String, Student> map = new HashMap<String,Student>();
map.put("st1", st1);
vs.push(map);
Student st2 = new Student("lisi",21);
vs.set("st2", st2);
//將root作為ArrayList放入資料
Student st3 = new Student("wisi",21);
vs.getRoot().add(st3);
System.out.println((Student)vs.getRoot().get(5));
通過如下可在頁面顯示及檢視值棧內容:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
name = <s:property value="name"/><br>
age = <s:property value="age"/><br>
st2.name = <s:property value="st2.name"/><br>
st2age = <s:property value="st2.age"/>
</body>
</html>
root的實質是ArrayList,所以裡面存的物件都是無名物件,只能通過物件的屬性來獲取相應值
context中資料載入順序:
當在Action中僅向context中放入某資料lov後,頁面無論是通過#從context讀取,還是不用#向root讀取,都能讀到(後者先去root找相關資料,沒有就在context下找)
String lov = "lov";
ActionContext.getContext().put("lov", lov);
lov = <s:property value="lov"/><br>
#lov = <s:property value="#lov"/><br>
當通過表單發出請求時,表單值傳到context.map下的request中,獲取其中的值時
# request.name底層執行的是request.getAttribute();
request.getAttribute();被struts2包裝後的查詢順序是:
request域空間->root->context
通過request = <%=request %>可以得出,這裡的request不是原始的request了:
以下為頁面中的一些OGNL操作(list,map遍歷,條件判斷,查詢)
<!-- set標籤定義的物件均存放於context中 -->
<!-- list -->
<s:set var="list" value="{'1','2','3'}"></s:set>
<s:iterator value="list"> <!-- iterator表情預設會將當前的迭代物件放入值棧棧頂 -->
<s:property/><br> <!-- property標籤預設輸出值棧棧頂元素 -->
</s:iterator>
<br>
<!-- map -->
<s:set var="map" value="#{'one':'1','two':'2' }"></s:set>
<s:iterator value="#map">
<s:property/><br>
</s:iterator>
<s:iterator value="#map" var="entry">
<s:property value="entry"/><br>
</s:iterator>
<s:iterator value="#map">
<s:property value="key"/>=<s:property value="value"/><br>
</s:iterator>
<!-- 集合元素判斷-->
<s:property value="'1' in #map"/>
<s:property value="'1' not in #map"/>
<!-- 集合投影 -->
<s:bean name="com.test.Student" var="st1" >
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="12"></s:param>
</s:bean>
<s:bean name="com.test.Student" var="st2">
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="13"></s:param>
</s:bean>
<s:bean name="com.test.Student" var="st3">
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="13"></s:param>
</s:bean>
<s:set var="students" value="{#st1,#st2,#st3}"></s:set>
<s:set var="studentsName" value="#students.{name}"></s:set>
<s:iterator value="#students">
<s:property/><br>
</s:iterator>
<s:iterator value="#studentsName">
<s:property/><br>
</s:iterator>
<!-- 集合查詢 -->
<s:iterator value="#students.{^#this.age>11}">
<s:property/><br>
</s:iterator>
<s:iterator value="#students.{$#this.age>11}">
<s:property/><br>
</s:iterator>