OGNL語法

8.1 OGNL語法

8.1.1 ActionContext、StackContext、ValueStack關係

ActionContext、StackContext、ValueStack對象與OGNL密切相關,理解三者之間的關係是掌握OGNL語法的根本。

1. ActionContext對象

ActionContext(com.opensymphony.xwork.ActionContext)是Action執行時的上下文,上下文可以看作是一個容器,它存放Action在執行時需要用到的對象,例如,請求的參數(Parameter)、會話(Session)、Servlet上下文(ServletContext)。在每次請求執行Action之前都會創建新的ActionContext。ActionContext是線程安全的,在同一個線程中ActionContext的屬性是唯一的。值得注意的是ActionContext不僅保存了Action在執行時需要用到的數據,本身也可存放數據,例如以下代碼用於將uid變量值保存到ActionContext對象中:

ActionContext.getContext().put("uid", "admin");

保存到ActionContext對象中的數據以後可通過Struts2標籤和EL表達式語言進行訪問。

2. StackContext 對象

Stack Context對象是ActionContext上下文中的一個java.util.Stack 實例。上述提及的請求參數(Parameter)、會話(Session)、Servlet上下文(ServletContext)等對象,實質是存儲在ActionContext上下文中的StackContext對象中。

3. ValueStack對象

Struts2會爲每一次Action的請求創建與之對應的ValueStack,並將所有Action屬性數據存儲到ValueStack中。再將ValueStack暴露給視圖頁面,這樣頁面就可直接訪問後臺處理生成的數據。

ActionContext、StackContext、ValueStack三者之間的關係如圖1.8.1所示:

       

 

圖 1.8.1 ActionContext、StackContext、ValueStack關係

 假設存在LoginAction控制器,代碼如下:

public class LoginAction

{

private String uid;//封裝用戶名

private String pwd;//封裝密碼

public String execute() throws Exception

{

       //獲取ActionContext對象  

ActionContext  ctx=ActionContext.getContext();

//將uid的值存儲到session中

ctx.getSession().put("uid", this.uid);

        //將uid的值存儲到Stack Context中

    ctx.put("uid", this.uid);

return "success";

}

//getter、setter代碼省略…

}

並且已經正確將該Action的uid屬性賦值爲scott,pwd屬性賦值爲tiger。則ActionContext、StackContext、ValueStack三者此時的數據存放情況如圖1.8.2所示:

 

圖1.8.2   LoginAction數據存儲情況

 

 

8.1.2 OGNL語法基礎

OGNL是Object-Graph Navigation Language(對象圖導航語言)的縮寫,它是一種功能強大的表達式語言,通過它的簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。

1.訪問OGNL上下文中的數據

ActionContext是Struts2中OGNL的上下文環境,也即向ActionContext中添加的數據(實際存儲在Stack Context中)都可以被OGNL來訪問,而ActionContext又包括request,session,ValueStack等這些對象,所以OGNL也可以訪問存儲在這些對象中的數據。

Value Stack(值棧)是OGNL的根,由於OGNL上下文中的根對象可以直接訪問,所以通過OGNL訪問Value Stack中的數據時不需要使用任何特殊的“標記”,而訪問ActionConext中的其他對象則需要使用“#”標記。在Struts2中提供了<s:property>標籤來訪問OGNL上下文中的數據。

(1) <s:property value=”uid”/>

運行該標籤時,Struts2會在Value Stack中去查找名爲uid項,並輸出其值

(2) <s:property value=”#uid”/>

運行該標籤時,Struts2會在StackContext中去查找名爲uid項,並輸出其值

(3) <s:property value=”#session.uid”/>

運行該標籤時,Struts2會在StackContext中的session作用域中去查找名爲uid項,並輸出其值。

(4) <s:property value=”#attr.uid”/>

運行該標籤時,Struts2會依次在StackContext的page,request,session,application範圍內查找對應的uid中的值。

2.訪問JavaBean屬性

假設存在employee對象作爲OGNL上下文的根對象,對於下面的表達式:

(1) <s:property value=”name”/>

運行該標籤時,Struts2會執行employee對象的getName()方法,對應的Java代碼是:employee.getName()

(2) <s:property value=”address.country”/>

運行該標籤時,Struts2會執行employee對象的getAddress()方法和getCountry()方法。對應的Java代碼是:employee.getAddress().getCountry()

3.執行JavaBean方法

OGNL不僅可以自動執行getter方法,還能執行JavaBean的其它方法,更重要的是,在執行方法時,還能給方法傳入參數。OGNL執行的方法或以靜態方法或非靜態方法。

執行靜態方法的格式爲:@類的全限名@方法名(參數),爲了能讓OGNL執行靜態方法,必須在struts.xml文件中配置常量,以開啓調用靜態方法功能,配置代碼如下:

<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>

以下示例演示了使用OGNL執行JavaBean方法:

(1) 創建一個JavaBean,命名爲OgnlInfo.java,代碼如下:

public class OgnlInfo {

//定義靜態方法

public static String  sayBye(String name)

{

return name+"再見!";

}

//定義非靜態方法

public String sayHello(String name)

{

return name+"你好!";

}

 }

(2) 創建index.jsp頁面,代碼如下:

  <body>

     <%

        //實例化ognl對象

        OgnlInfo ognlInfo=new OgnlInfo();

        //將ognlInfo對象存入request作用域內

        request.setAttribute("ognlInfo",ognlInfo);

      %>

     <!-- 執行ognl對象的非靜態方法 -->

    <s:property value="#request.ognlInfo.sayHello('jack')"/>

     <!-- 執行ognl對象的靜態方法 -->

<s:property value="@com.soft.struts8l.entity.OgnlInfo@sayBye('tom')"/>

  </body>

運行index.jsp頁面,結果如圖1.8.3所示:

 圖1.8.3 OGNL執行JavaBean的方法

4.OGNL操作符號

OGNL表達式中能使用的操作符基本跟Java裏的操作符一樣,除了能使用 +, -, *, /, ==, !=, = 等操作符之外,還能使用 mod(取餘), in, not in等

5. %符號

%符號的用途是在標誌的屬性爲字符串類型時,計算OGNL表達式的值。以下示例代碼用於演示%符號在OGNL中的使用方法。

  <body>

    <%

       String title="提交";

       pageContext.setAttribute("title",title);

     %>     

      不使用%符號,會按原樣顯示

      <s:submit value="#attr.title"/><hr>

      使用%符號,會計算OGNL表達式的值

      <s:submit value="%{#attr.title}"/>

   </body>

運行此示例,結果如圖1.8.4 所示:

 

圖1.8.4 OGNL %符號的用法

6. OGNL中的集合操作

 (1) 生成List類型集合

     {e1,e2,e3 . . . } 

     以上語法,直接生成一個List類型集合,該集合包含了3個元素:e1、e2和e3。如果需要更多元素,則多個元素之間以英文逗號隔開。

(2) 生成Map類型集合

     #{key1:value1,key2:value2,. . . }

    以上語法,直接生成一個Map類型集合,該Map中每個key-value對象之間以英文冒號隔開;多項之間以英文逗號隔開。

 (3) 使用in 和 not in 運算符

   對於集合,OGNL提供兩上元素符:in和not in,其中in判斷某個元素是否在指定集合中;not in則用於判斷某個元素是否不在指定集合中。以下代碼演示了in和not in的用法:

        <!-- 判斷java是否在指定集合中 -->

     <s:if test=" 'java' in {'java','jsp','html'}">

         在裏面

        <s:else>

                不在裏面

           </s:else>

        </s:if>

 

(4) 獲取集合的子集

    OGNL允許通過某個規則取得集合的子集。取得子集時有以下3種操作符:

    ?:取出所有符合選擇邏輯的元素

    ^:取出符合選擇邏輯的第一個元素

    $:取出符合選擇邏輯的最後一個元素

    假定在session作用域中存在名爲persons集合, 該集合由多個Person類的實例組成, 在Person類中存在一個age屬性,用於描述年齡,則#session.persons.{? #this.age>20} 表達式用於取出年齡大於20的persons類子集合;#session.persons.{? ^this.age>20} 表達式用於取出第一個年齡大於20的Person類實例;#session.persons.{? ^this.age>20} 表達式用於取出最後一個年齡大於20的Person類實例。   

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章