1. 程式人生 > >struts2-OGNL基礎

struts2-OGNL基礎

OGNL(Object-Graph Navigation Language)是一種強大的表示式語言,是一個第三方開源專案。

OGNL本身是與struts2 沒有任何關係 ,但struts2框架使用了OGNL用於進行表示式的計算工作。struts2通過使用OGNL簡單一致的表示式語法,可以存取物件的任意屬性,呼叫物件的方法,遍歷整個物件的結構圖,實現欄位型別轉換等功能。

OGNL特點:

  • 支援物件方法呼叫
  • 可以操作集合物件
  • 可以直接建立物件
  • 支援類靜態方法呼叫和常量訪問,表示式的格式為:
    @[全限定性類名]@[方法名|常量名]
    如:@[email protected]
    (“123”)或@[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>