Struts2中的OGNL詳解

首先了解下OGNL的概念

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

此外,還得先需弄懂OGNL的一些知識:

1.OGNL表達式的計算是圍繞OGNL上下文進行的。
OGNL上下文實際上就是一個Map對象,由ognl.OgnlContext類表示。它裏面可以存放很多個JavaBean對象。它有一個上下文根對象。
上下文中的根對象可以直接使用名來訪問或直接使用它的屬性名訪問它的屬性值。否則要加前綴“#key”。

2.Struts2的標籤庫都是使用OGNL表達式來訪問ActionContext中的對象數據的。如:<s:propertyvalue="xxx"/>。

3.Struts2將ActionContext設置爲OGNL上下文,並將值棧作爲OGNL的根對象放置到ActionContext中。

4.值棧(ValueStack) :
可以在值棧中放入、刪除、查詢對象。訪問值棧中的對象不用“#”。
Struts2總是把當前Action實例放置在棧頂。所以在OGNL中引用Action中的屬性也可以省略“#”。

5.調用ActionContext的put(key,value)放入的數據,需要使用#訪問。

OGNL中重要的3個符號:#、%、$:

#、%和$符號在OGNL表達式中經常出現,而這三種符號也是開發者不容易掌握和理解的部分,需要時間的積累才漸漸弄清楚……
1.#符號

#符號的用途一般有三種。

—    訪問非根對象屬性,例如#session.msg表達式,由於Struts 2中值棧被視爲根對象,所以訪問其他非根對象時,需要加#前綴。實際上,#相當於ActionContext. getContext();#session.msg表達式相當於ActionContext.getContext().getSession(). getAttribute("msg") 。

—    用於過濾和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。

—    用來構造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。

2.%符號

%符號的用途是在標誌的屬性爲字符串類型時,計算OGNL表達式的值,這個類似js中的eval,很暴力。

3.$符號

$符號主要有兩個方面的用途。

—    在國際化資源文件中,引用OGNL表達式,例如國際化資源文件中的代碼:reg.agerange=國際化資源信息:年齡必須在${min}同${max}之間。

—    在Struts 2框架的配置文件中引用OGNL表達式,例如:

  <span style="font-size:12px;">  <validators>    
        <field name="intb">    
                <field-validator type="int">    
                <param name="min">10</param>    
                <param name="max">100</param>    
                <message>BAction-test校驗:數字必須爲${min}爲${max}之間!</message>    
            </field-validator>    
        </field>    
    </validators>   </span>

下面通過代碼對OGNL有更深的瞭解:

action類OgnlAction.java:
   <span style="font-size:12px;"> package com.tjcyjd.test.action;  
      
    import java.util.Date;  
    import java.util.LinkedList;  
    import java.util.List;  
      
    import javax.servlet.http.HttpServletRequest;  
      
    import org.apache.struts2.ServletActionContext;  
    import org.apache.struts2.convention.annotation.Action;  
    import org.apache.struts2.convention.annotation.Namespace;  
    import org.apache.struts2.convention.annotation.ParentPackage;  
    import org.apache.struts2.convention.annotation.Result;  
    import org.apache.struts2.convention.annotation.Results;  
    import org.springframework.stereotype.Controller;  
      
    import com.opensymphony.xwork2.ActionContext;  
    import com.opensymphony.xwork2.ActionSupport;  
      
    @Controller  
    @Namespace("/test")  
    @ParentPackage("struts-default")  
    @Results( { @Result(name = "success", location = "/other_test/showognl.jsp"),  
            @Result(name = "fail", location = "/bbs/admin_login.jsp"),  
            @Result(name = "input", location = "/bbs/admin_login.jsp") })  
    public class OgnlAction extends ActionSupport {  
        private static final long serialVersionUID = -1494290883433357310L;  
        private List<Person> persons;  
      
        @Action("ognlTest")  
        public String ognlTest() throws Exception {  
            // 獲得ActionContext實例,以便訪問Servlet API  
            ActionContext ctx = ActionContext.getContext();  
            // 存入application  
            ctx.getApplication().put("msg", "application信息");  
            // 保存session  
            ctx.getSession().put("msg", "seesion信息");  
            // 保存request信息  
            HttpServletRequest request = ServletActionContext.getRequest();  
            request.setAttribute("msg", "request信息");  
            // 爲persons賦值  
            persons = new LinkedList<Person>();  
            Person person1 = new Person();  
            person1.setName("pla1");  
            person1.setAge(26);  
            person1.setBirthday(new Date());  
            persons.add(person1);  
      
            Person person2 = new Person();  
            person2.setName("pla2");  
            person2.setAge(36);  
            person2.setBirthday(new Date());  
            persons.add(person2);  
      
            Person person3 = new Person();  
            person3.setName("pla3");  
            person3.setAge(16);  
            person3.setBirthday(new Date());  
            persons.add(person3);  
      
            return SUCCESS;  
      
        }  
      
        public List<Person> getPersons() {  
            return persons;  
        }  
      
        public void setPersons(List<Person> persons) {  
            this.persons = persons;  
        }  
    }  </span>
jsp頁面showognl.jsp:

 <span style="font-size:12px;">   <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>    
        
    <%@ taglib prefix="s" uri="/struts-tags" %>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">    
        
    <html xmlns="http://www.w3.org/1999/xhtml">    
        
    <head>    
        
        <title>Struts2 OGNL 演示</title>    
        
    </head>    
        
    <body>        
        
        <h3>訪問OGNL上下文和Action上下文</h3>    
        
        <!-使用OGNL訪問屬性值-->    
        
        <p>parameters: <s:property value="#parameters.msg" /></p>    
        
        <p>request.msg: <s:property value="#request.msg" /></p>    
        
        <p>session.msg: <s:property value="#session.msg" /></p>    
        
        <p>application.msg: <s:property value="#application.msg" /></p>    
        
        <p>attr.msg: <s:property value="#attr.msg" /></p>    
        
        <hr />    
        
        <h3>用於過濾和投影(projecting)集合</h3>    
        
        <p>年齡大於20</p>    
        
        <ul>    
        
        <!-判斷年齡-->    
        
            <s:iterator value="persons.{?#this.age>20}">    
        
                <li><s:property value="name" /> - 年齡:<s:property value="age" /></li>    
        
            </s:iterator>    
        
        </ul>    
        
        <p>姓名爲pla1的年齡: <s:property value="persons.{?#this.name=='pla1'}.{age}[0]"/></p>    
        
        <hr />    
        
        <h3>構造Map</h3>    
        
        <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />    
        
        <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>    
          
        <hr />   
          
        <h4>%符號的用法</h4>    
        
        <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />    
        
        <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>    
        
        <p>不使用%:<s:url value="#foobar['foo1']" /></p>    
        
        <p>使用%:<s:url value="%{#foobar['foo1']}" /></p>    
        
        <hr />  
            <%    
                request.setAttribute("req", "request scope");    
                request.getSession().setAttribute("sess", "session scope");    
                request.getSession().getServletContext().setAttribute("app",    
                        "aplication scope");    
            %>    
            1.通過ognl表達式獲取 屬性範圍中的值    
            <br>    
            <s:property value="#request.req" />    
            <br />    
            <s:property value="#session.sess" />    
            <br />    
            <s:property value="#application.app" />    
            <br />    
            <hr>    
        
           2.通過<span style="background-color: #fafafa;">ognl表達式創建list 集合 ,並且遍歷出集合中的值    
            <br>    
            <s:set name="list" value="{'eeeee','ddddd','ccccc','bbbbb','aaaaa'}"></s:set>    
            <s:iterator value="#list" var="o">    
                <!-- ${o }<br/> -->    
                <s:property />    
                <br />    
            </s:iterator>    
            <br />    
            <hr>    
        
           3.通過ognl表達式創建Map 集合 ,並且遍歷出集合中的值    
            <br>    
            <s:set name="map"    
                value="#{'1':'eeeee','2':'ddddd','3':'ccccc','4':'bbbbb','5':'aaaaa'}"></s:set>    
            <s:iterator value="#map" var="o">    
                <!--      ${o.key }->${o.value }<br/>   -->    
                <!-- <s:property value="#o.key"/>-><s:property value="#o.value"/><br/>   -->    
                <s:property value="key" />-><s:property value="value" />    
                <br />    
            </s:iterator>    
            <br />    
            <hr>    
          4.通過ognl表達式 進行邏輯判斷    
            <br>    
            <s:if test="'aa' in {'aaa','bbb'}">    
                aa 在 集合{'aaa','bbb'}中;    
            </s:if>    
            <s:else>    
                aa 不在 集合{'aaa','bbb'}中;    
            </s:else>    
            <br />    
            <s:if test="#request.req not in #list">    
                    不 在 集合list中;    
            </s:if>    
            <s:else>    
                 在 集合list中;    
            </s:else>    
            <br />    
            <hr>    
              
           5.通過ognl表達式 的投影功能進行數據篩選    
            <br>    
            <s:set name="list1" value="{1,2,3,4,5}"></s:set>    
            <s:iterator value="#list1.{?#this>2}" var="o">    
                <!-- #list.{?#this>2}:在list1集合迭代的時候,從中篩選出當前迭代對象>2的集合進行顯示 -->    
                ${o }<br />    
            </s:iterator>    
            <br />    
            <hr>    
           6.通過ognl表達式 訪問某個類的靜態方法和值    
            <br>    
            <s:property value="@java.lang.Math@floor(32.56)" />    
        
            <s:property value="@com.rao.struts2.action.OGNL1Action@aa" />    
            <br />    
            <br />    
            <hr>    
          7.ognl表達式 迭代標籤 詳細    
            <br>    
            <s:set name="list2"    
                value="{'aa','bb','cc','dd','ee','ff','gg','hh','ii','jj'}"></s:set>    
            <table border="1">    
                <tr>    
                    <td>索引 </td>    
                    <td>值</td>    
                    <td>奇?</td>    
                    <td> 偶?</td>    
                    <td>首?</td>    
                    <td> 尾?</td>    
                    <td>當前迭代數量</td>    
                </tr>    
                <s:iterator value="#list2" var="o" status="s">    
                    <tr bgcolor="<s:if test="#s.even">pink</s:if>">    
                        <td>    
                            <s:property value="#s.getIndex()" />    
                        </td>    
                        <td>    
                            <s:property />    
                        </td>    
                        <td>    
                            <s:if test="#s.odd">Y</s:if>    
                            <s:else>N</s:else>    
                        </td>    
                        <td>    
                            <s:if test="#s.even">Y</s:if>    
                            <s:else>N</s:else>    
                        </td>    
                        <td>    
                            <s:if test="#s.first">Y</s:if>    
                            <s:else>N</s:else>    
                        </td>    
                        <td>    
                            <s:if test="#s.isLast()">Y</s:if>    
                            <s:else>N</s:else>    
                        </td>    
                        <td>    
                        <s:property value="#s.getCount()"/>    
                    </td>    
                    </tr>    
                </s:iterator>    
            </table>    
            <br>    
            <hr>         
              
              
           8.ognl表達式:  if/else if/else 詳細<br>    
            <% request.setAttribute("aa",0); %>    
            <s:if test="#request.aa>=0 && #request.aa<=4">    
                    在0-4之間;    
            </s:if>    
            <s:elseif test="#request.aa>=4 && #request.aa<=8">    
                    在4-8之間;    
            </s:elseif>    
            <s:else>    
                 大於8;    
            </s:else>    
            <br>    
            <hr>    
        9.ognl表達式: url 詳細<br>    
            <% request.setAttribute("aa","sss"); %>    
            <s:url action="testAction" namespace="/aa/bb">    
                <s:param name="aa" value="#request.aa"></s:param>    
                <s:param name="id">100</s:param>    
            </s:url>    
            <br/>    
            <s:set name="myurl" value="'http://www.baidu.com'"></s:set>    
            value以字符處理:   <s:url value="#myurl"></s:url><br>    
            value明確指定以ognl表達式處理:    <s:url value="%{#myurl}"></s:url>    
            <br>    
            <hr>    
        10.ognl表達式: checkboxlist 詳細<br>    
            1> .list 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>    
            name:checkboxlist的名字<br>    
            list:checkboxlist要顯示的列表<br>    
            value:checkboxlist默認被選中的選項,checked=checked<br>    
            <s:checkboxlist name="checkbox1" list="{'上網','看書','爬山','游泳','唱歌'}" value="{'上網','看書'}" ></s:checkboxlist>    
            <br>    
             以上生成代碼:<br>    
            <xmp>    
                <input type="checkbox" name="checkbox1" value="上網" id="checkbox1-1" checked="checked"/>    
                <label for="checkbox1-1" class="checkboxLabel">上網</label>    
                <input type="checkbox" name="checkbox1" value="看書" id="checkbox1-2" checked="checked"/>    
                <label for="checkbox1-2" class="checkboxLabel">看書</label>    
                <input type="checkbox" name="checkbox1" value="爬山" id="checkbox1-3"/>    
                <label for="checkbox1-3" class="checkboxLabel">爬山</label>    
                <input type="checkbox" name="checkbox1" value="游泳" id="checkbox1-4"/>    
                <label for="checkbox1-4" class="checkboxLabel">游泳</label>    
                <input type="checkbox" name="checkbox1" value="唱歌" id="checkbox1-5"/>    
                <label for="checkbox1-5" class="checkboxLabel">唱歌</label>"    
            </xmp>    
            2> .Map 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>    
            name:checkboxlist的名字<br>    
            list:checkboxlist要顯示的列表<br>    
            listKey:checkbox 的value的值<br>    
            listValue:checkbox 的lablel(顯示的值)<br>    
            value:checkboxlist默認被選中的選項,checked=checked<br>    
            <s:checkboxlist name="checkbox2" list="#{1:'上網',2:'看書',3:'爬山',4:'游泳',5:'唱歌'}" listKey="key" listValue="value" value="{1,2,5}" ></s:checkboxlist>    
            <br>    
                           以上生成代碼:<br>    
            <xmp>    
                <input type="checkbox" name="checkbox2" value="1" id="checkbox2-1" checked="checked"/>    
                <label for="checkbox2-1" class="checkboxLabel">上網</label>    
                <input type="checkbox" name="checkbox2" value="2" id="checkbox2-2" checked="checked"/>    
                <label for="checkbox2-2" class="checkboxLabel">看書</label>    
                <input type="checkbox" name="checkbox2" value="3" id="checkbox2-3"/>    
                <label for="checkbox2-3" class="checkboxLabel">爬山</label>    
                <input type="checkbox" name="checkbox2" value="4" id="checkbox2-4"/>    
                <label for="checkbox2-4" class="checkboxLabel">游泳</label>    
                <input type="checkbox" name="checkbox2" value="5" id="checkbox2-5" checked="checked"/>    
                <label for="checkbox2-5" class="checkboxLabel">唱歌</label>    
            </xmp>    
            <hr>    
    </body>    
    </html>    </span>
總結OGNL的使用方法:

訪問屬性

名字屬性獲取:<s:property value="user.username"/><br>

地址屬性獲取:<s:property value="user.address.addr"/><br>

訪問方法

調用值棧中對象的普通方法:<s:property value="user.get()"/><br>

訪問靜態屬性和方法

調用Action中的靜態方法:<s:property value="@struts.action.LoginAction@get()"/>

調用JDK中的類的靜態方法:<s:property value="@java.lang.Math@floor(44.56)"/><br>

調用JDK中的類的靜態方法(同上):<s:property value="@@floor(44.56)"/><br>

調用JDK中的類的靜態方法:<s:property value="@java.util.Calendar@getInstance()"/><br>

調用普通類中的靜態屬性:<s:property value="@struts.vo.Address@TIPS"/><br>

訪問構造方法

調用普通類的構造方法:<s:property value="new struts.vo.Student('李曉紅' , '美女' , 3 , 25).username"/>

 

1.5. 訪問數組

獲取List:<s:property value="testList"/><br>

獲取List中的某一個元素(可以使用類似於數組中的下標獲取List中的內容):

<s:property value="testList[0]"/><br>

獲取Set:<s:property value="testSet"/><br>

獲取Set中的某一個元素(Set由於沒有順序,所以不能使用下標獲取數據):

<s:property value="testSet[0]"/><br> ×

獲取Map:<s:property value="testMap"/><br>

獲取Map中所有的鍵:<s:property value="testMap.keys"/><br>

獲取Map中所有的值:<s:property value="testMap.values"/><br>

獲取Map中的某一個元素(可以使用類似於數組中的下標獲取List中的內容):

<s:property value="testMap['m1']"/><br>

獲取List的大小:<s:property value="testSet.size"/><br>

 

訪問集合 – 投影、選擇(? ^ $)

利用選擇獲取List中成績及格的對象:<s:property value="stus.{?#this.grade>=60}"/><br>

利用選擇獲取List中成績及格的對象的username:

<s:property value="stus.{?#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的第一個對象的username:

<s:property value="stus.{?#this.grade>=60}.{username}[0]"/><br>

利用選擇獲取List中成績及格的第一個對象的username:

<s:property value="stus.{^#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的最後一個對象的username:

<s:property value="stus.{$#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的第一個對象然後求大小:

<s:property value="stus.{^#this.grade>=600}.{username}.size"/><br>

集合的僞屬性

OGNL能夠引用集合的一些特殊的屬性,這些屬性並不是JavaBeans模式,例如size(),length()等等. 當表達式引用這些屬性時,OGNL會調用相應的方法,這就是僞屬性.

集合

僞屬性

Collection(inherited by Map, List & Set)

size ,isEmpty

List

iterator

Map

keys , values

Set

iterator

Iterator

next , hasNext

Enumeration

next , hasNext , nextElement , hasMoreElements

 

Lambda   :[…]

格式::[…]

使用Lambda表達式計算階乘:

<s:property value="#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)"/><br>

OGNL中#的使用

#可以取出堆棧上下文中的存放的對象.

名稱

作用

例子

parameters

包含當前HTTP請求參數的Map

#parameters.id[0]作用相當於

request.getParameter("id")

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)














獲取Paraments對象的屬性:<s:property value="#parameters.username"/>

OGNL中%的使用

用%{}可以取出存在值堆棧中的Action對象,直接調用它的方法.

例如你的Action如果繼承了ActionSupport .那麼在頁面標籤中,用%{getText('key')}的方式可以拿出國際化信息.

OGNL中$的使用

“$”有兩個主要的用途

  用於在國際化資源文件中,引用OGNL表達式

  在Struts 2配置文件中,引用OGNL表達式

值棧

ValueStack對象。這個對象貫穿整個Action的生命週期(每個Action類的對象實例會擁有一個ValueStack對象)。當Struts 2接收到一個.action的請求後,會先建立Action類的對象實例,但並不會調用Action方法,而是先將Action類的相應屬性放到ValueStack對象的頂層節點(ValueStack對象相當於一個棧)。

在Action中獲得ValueStack對象:ActionContext.getContext().getValueStack()

 Top語法

使用Top獲取值棧中的第二個對象:<s:property value="[1].top.對象"/>

 N語法

使用N獲取值棧中的第二個對象:<s:property value="[1].對象"/>

 @語法

調用action中的靜態方法:<s:property value="@vs1@靜態方法"/> vs:值棧 1:表示第一個。



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