隨筆-126  評論-247  文章-5  trackbacks-0

          OGNL

          OGNL ( Object Graph Navigation Language ),對象圖導(dǎo)航語言。這是一種強大的表達(dá)式語言,通過它可以非常方便的來操作對象屬性。
          在 Struts2 中,OGNL 需要和 Struts2 標(biāo)簽庫配套來使用。

          OGNL context

                                         |
                                         | -- application
                                         |
                                         | -- session
                                         |
                                         | -- value  stack ( root )
          context  map  ---- |
                                         | -- request
                                         |
                                         | -- parameters
                                         |
                                         | -- attr ( searches page, request, session, then application scopes )
                                         |
          Struts2 框架將 OGNL context 設(shè)置為我們的 ActionContext,并將 ValueStack 作為 OGNL 的根對象。而 Action 則置于 ValueStack 的最頂層。
          除此之外,Struts2 框架還把代表 application、request、session 對象的 Map 對象也放到 ActionContext 中,使得 Action 與 Servlet API 解耦。
          名稱 描述
          ValueStack 值棧,作為 OGNL 上下文的根對象。通過 KEY 來訪問,非根對象需要用 #KEY 來訪問
          parameters Map 類型,封裝了請求中的所有參數(shù)。訪問 #parameters.name 相當(dāng)于調(diào)用 HttpServletRequest.getParameter( )
          request Map 類型,封裝了 request 對象中的所有屬性。訪問 #request.name 相當(dāng)于調(diào)用 HttpServletRequest.getAttribute( )
          session Map 類型,封裝了 session 對象中的所有屬性。訪問 #session.name 相當(dāng)于調(diào)用 HttpSession.getAttribute( )
          application Map 類型,封裝了 application 對象中的所有屬性。訪問 #application.name 相當(dāng)于調(diào)用 ServletContext.getAttribute( )
          attr Map 類型,依次從 page、request、session、application 對象中檢索屬性的值

          OGNL 訪問 Action 中的數(shù)據(jù)

          Action 位于值棧的棧頂位置,而值棧又是 OGNL 的根對象,因此,在 OGNL 表達(dá)式中可直接使用屬性名稱來訪問 Action 當(dāng)中的數(shù)據(jù)。如:
          <s:property value="name" />
          實際上,這里是通過調(diào)用 Action 當(dāng)中的 getName( ) 方法來獲取得到數(shù)據(jù)的,而不管 Action 當(dāng)中是否有一個名稱為 name 的屬性變量。
          因此,如果需要在頁面中獲取得到 Action 當(dāng)中的數(shù)據(jù),你只需要為你的 Action 類編寫 getXX( ) 方法就可以了。

          測試環(huán)境

          package fan.tutorial.model;

          import java.util.Set;

          public class Person {

              private String sex;
              private String name;
              private IDCard idcard;
              private Set<Address> addressSet;
              public static final double VERSION = 1.0;
              
              public Person(){}
              
              public Person(String name, String sex, IDCard idcard, Set<Address> addressSet){
                  this.sex = sex;
                  this.name = name;
                  this.idcard = idcard;
                  this.addressSet = addressSet;
              }

              public String getSex() {
                  return sex;
              }

              public void setSex(String sex) {
                  this.sex = sex;
              }

              public String getName() {
                  return name;
              }

              public void setName(String name) {
                  this.name = name;
              }

              public Set<Address> getAddressSet() {
                  return addressSet;
              }

              public void setAddressSet(Set<Address> addressSet) {
                  this.addressSet = addressSet;
              }

              public IDCard getIdcard() {
                  return idcard;
              }

              public void setIdcard(IDCard idcard) {
                  this.idcard = idcard;
              }

              public static double getVersion() {
                  return VERSION;
              }
          }
          package fan.tutorial.model;

          public class IDCard {

              private long number;
              
              public IDCard(){}
              
              public IDCard(long number){
                  this.number = number;
              }

              public long getNumber() {
                  return number;
              }

              public void setNumber(long number) {
                  this.number = number;
              }
          }
          package fan.tutorial.model;

          public class Address {

              private String name;
              
              public Address(){}
              
              public Address(String name){
                  this.name = name;
              }

              public String getName() {
                  return name;
              }

              public void setName(String name) {
                  this.name = name;
              }
          }
          package fan.tutorial.action;

          import java.util.Map;
          import java.util.Set;
          import java.util.List;
          import java.util.HashSet;
          import java.util.ArrayList;
          import java.util.LinkedHashMap;
          import fan.tutorial.model.IDCard;
          import fan.tutorial.model.Person;
          import fan.tutorial.model.Address;
          import com.opensymphony.xwork2.Action;
          import org.apache.struts2.interceptor.RequestAware;
          import org.apache.struts2.interceptor.SessionAware;
          import org.apache.struts2.interceptor.ApplicationAware;

          public class DataAction implements Action, RequestAware, SessionAware, ApplicationAware {
              
              private String author;
              private String subject;
              private Person person;
              private List<Person> personList;
              private Map<String, String> map;
              private Map<String, Object> request;
              private Map<String, Object> session;
              private Map<String, Object> application;
              private int[] array = {8, 0, 9, 1, 3, 4, 2, 5, 7, 6};

              public String execute() throws Exception {
                  
                  subject = "fan-tutorial";
                  
                  Set<Address> addressSet = new HashSet<Address>(2);
                  addressSet.add(new Address("廣東茂名"));
                  addressSet.add(new Address("廣東廣州"));
                  person = new Person("fan", "male", new IDCard(3115981L), addressSet);
                  
                  personList = new ArrayList<Person>(3);
                  addressSet = new HashSet<Address>(1);
                  addressSet.add(new Address("云南麗江"));
                  personList.add(person);
                  personList.add(new Person("chen", "female", new IDCard(3575982L), addressSet));
                  addressSet = new HashSet<Address>(1);
                  addressSet.add(new Address("廣東潮汕"));
                  personList.add(new Person("chai", "female", new IDCard(3115983L), addressSet));
                  
                  map = new LinkedHashMap<String, String>(2);
                  map.put("username", "fan");
                  map.put("password", "yun");
                  
                  request.put("message", "hey request");
                  session.put("message", "hey session");
                  application.put("message", "hey application");
                  
                  return SUCCESS;
                  
              }

              public String getSubject() {
                  return subject;
              }

              public Person getPerson() {
                  return person;
              }

              public List<Person> getPersonList() {
                  return personList;
              }

              public int[] getArray() {
                  return array;
              }

              public Map<String, String> getMap() {
                  return map;
              }

              public String getAuthor() {
                  return author;
              }

              public void setAuthor(String author) {
                  this.author = author;
              }

              public void setRequest(Map<String, Object> request) {
                  this.request = request;
              }

              public void setSession(Map<String, Object> session) {
                  this.session = session;
              }

              public void setApplication(Map<String, Object> application) {
                  this.application = application;
              }
          }
          <struts>

            <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
            
            <package name="default" extends="struts-default">
              <default-action-ref name="defaultAction" />
              <action name="defaultAction">
                <result type="redirect">test?author=fan</result>
              </action>
              <action name="test" class="fan.tutorial.action.DataAction">
                <result>/index.jsp</result>
              </action>
            </package>

          </struts>

          OGNL 訪問對象屬性

          <s:property value="subject"/>
          <s:property value="person.name"/>
          <s:property value="person.idcard.number"/>

          OGNL 調(diào)用方法

          <s:property value="person.getName()"/>
          <s:property value="person.name.toUpperCase()"/>

          OGNL 調(diào)用靜態(tài)屬性

          <s:property value="@fan.tutorial.model.Person@VERSION"/>

          OGNL 調(diào)用靜態(tài)方法

          <!-- 在 struts.xml 中添加下面這行配置 -->
          <!-- <constant name="struts.ognl.allowStaticMethodAccess" value="true"/> -->
          <s:property value="@fan.tutorial.model.Person@getVersion()"/>

          OGNL 調(diào)用構(gòu)造方法

          <s:property value="new fan.tutorial.model.Address('廣東茂名').name"/>

          OGNL 使用索引訪問數(shù)組和列表

          <s:property value="array[0]"/>
          <s:property value="personList[0].name"/>

          OGNL 操作符運算

          <s:property value="array[0] + 1"/>
          <s:property value="array[0] - 1"/>
          <s:property value="array[0] * 2"/>
          <s:property value="array[0] / 2"/>
          <s:property value="array[0] % 3"/>

          OGNL 邏輯運算符

          <s:set name="x" value="5"/>
          <s:property value="#x in array"/>
          <s:property value="#x not in array"/>
          <s:property value="#x > array[0]"/>
          <s:property value="#x >= array[0]"/>
          <s:property value="#x < array[0]"/>
          <s:property value="#x <= array[0]"/>
          <s:property value="#x == array[0]"/>
          <s:property value="#x != array[0]"/>

          OGNL 訪問命名對象 ( parameters、request、session、application、attr )

          <s:property value="#parameters.author"/>
          <s:property value="#request.message"/>
          <s:property value="#session.message"/>
          <s:property value="#application.message"/>
          <s:property value="#attr.message"/>

          OGNL 訪問集合的偽屬性

          類型 偽屬性 偽屬性對應(yīng)的 Java 方法
          List
          Set
          Map
          size
          isEmpty
          List.size()        List.isEmpty()
          Set.size()        Set.isEmpty()
          Map.size()       Map.isEmpty()
          List
          Set
          iterator List.iterator()
          Set.iterator()
          Map keys
          values
          Map.keySet()
          Map.values()
          Iterator next
          hasNext
          Iterator.next()
          Iterator.hasNext()
          <s:property value="personList.size"/>
          <s:property value="personList.isEmpty"/>
          <s:property value="map.keys"/>
          <s:property value="map.values"/>
          <s:property value="personList.iterator.hasNext"/>
          <s:property value="personList.iterator.next.name"/>
          <s:property value="person.addressSet.iterator.hasNext"/>
          <s:property value="person.addressSet.iterator.next.name"/>

          OGNL 迭代集合

          類型 偽屬性 偽屬性的作用描述
          IteratorStatus index 當(dāng)前元素的索引
          IteratorStatus first 當(dāng)前元素是否是集合的第一個元素
          IteratorStatus last 當(dāng)前元素是否是集合的最后一個元素
          IteratorStatus count 當(dāng)前迭代元素的數(shù)量,count = index + 1
          IteratorStatus even index + 1 是否為偶數(shù)
          IteratorStatus odd index + 1 是否為奇數(shù)
          <table>
            <tr align="center">
              <td width="2%">索引</td>
              <td width="5%"></td>
              <td width="8%">當(dāng)前迭代的數(shù)量</td>
              <td width="8%">迭代奇偶性</td>
              <td width="8%">集合第一個元素</td>
              <td width="8%">集合最后一個元素</td>
            </tr>
            <s:iterator value="array" var="a" status="status">
              <tr align="center">
                <td>
                  <s:property value="#status.index"/>
                </td>
                <td>
                  <s:property/>
                </td>
                <td>
                  <s:property value="#status.count"/>
                </td>
                <td>
                  <s:if test="#status.even"></s:if>
                  <s:if test="#status.odd"></s:if>
                </td>
                <td>
                  <s:if test="#status.first"></s:if>
                  <s:else></s:else>
                </td>
                <td>
                  <s:if test="#status.last"></s:if>
                  <s:else></s:else>
                </td>
              </tr>
            </s:iterator>
          </table>

          OGNL 投影

          如果把集合中的數(shù)據(jù)想象成是數(shù)據(jù)庫表中的數(shù)據(jù),那么,投影就是從這張表中選取某一列所構(gòu)成的一個新的集合。投影的語法:collection.{expression}
          <s:property value="personList.{name}"/>

          OGNL 過濾

          OGNL 過濾也稱為選擇,就是把滿足 OGNL 表達(dá)式的結(jié)果選擇出來構(gòu)成一個新的集合。
          過濾的語法:collection.{?expression} 或 collection.{^expression} 或 collection.{$expression}
          符號 作用
          ? 選取與邏輯表達(dá)式匹配的所有結(jié)果
          ^ 選取與邏輯表達(dá)式匹配的第一個結(jié)果
          $ 選擇與邏輯表達(dá)式匹配的最后一個結(jié)果
          #this 代表當(dāng)前迭代的元素
          <s:property value="array.{?#this > 5}"/>
          <s:property value="array.{^#this > 5}"/>
          <s:property value="array.{$#this > 5}"/>

          OGNL 投影和過濾

          <s:property value="personList.{?#this.sex.equals('female')}.{name}"/>
          <s:property value="personList.{^#this.sex.equals('female')}.{name}"/>
          <s:property value="personList.{$#this.sex.equals('female')}.{name}"/>

          OGNL %{ } 語法

          對于 ${ } 也許你并不會陌生,${ } 是 EL 表達(dá)式的語法,這里的 %{ } 是 OGNL 表達(dá)式的語法。
          也許你開始困惑,上面示例不是都在使用 OGNL 表達(dá)式嗎?!沒見 %{ } 出現(xiàn)過啊!好眼力!凡是屬于 OGNL 表達(dá)式的串,你都可以使用 %{ } 來將它們包裹住,但這不是必須的。例如 <s:property value="expression" /> 中的 expression 在任何時候都是被當(dāng)做 OGNL 表達(dá)式來處理的。
          <s:property value="subject"/>  <!-- subject被OGNL進行表達(dá)式求值輸出 -->
          <s:property value="i love java so much"/>  <!-- 什么都不輸出 -->
          第2行之所以什么都不輸出,是因為執(zhí)行時環(huán)境把 i love java so much 這個字符串也當(dāng)做是一個 OGNL 表達(dá)式來處理了,但在 OGNL 上下文中并找不到與這個 KEY 對應(yīng)的值,因此什么都沒有輸出。
          這是由于 <s:property /> 標(biāo)簽的 value 屬性是 Object 類型引起的,凡是 Object 類型的標(biāo)簽屬性的值,都會被當(dāng)做是一個 OGNL 表達(dá)式來處理。
          這種情況下的解決辦法是:使用單引號將它們引起來,表明這是一個普通的字符串,而不是 OGNL 表達(dá)式。
          <s:property value="'subject'"/>  <!-- 輸出 subject -->
          <s:property value="'i love java so much'"/>  <!-- 輸出 i love java so much -->
          再如 <s:textfield value="expression" /> 中的 expression 什么時候被當(dāng)做 OGNL 表達(dá)式來處理就要取決于你是否使用了 %{ } 語法,如果使用了,那么它就是一個 OGNL 表達(dá)式,如果沒有使用,那么它就只是一個普通的字符串而已。
          <s:textfield value="author"/>         <!-- author被當(dāng)做普通字符串原樣輸出 -->
          <s:textfield value="%{author}"/>      <!-- author被OGNL進行表達(dá)式求值輸出 -->
          <s:textfield value="person.name"/>    <!-- person.name被當(dāng)做普通字符串原樣輸出 -->
          <s:textfield value="%{person.name}"/> <!-- person.name被OGNL進行表達(dá)式求值輸出 -->
          這是由于 <s:textfield /> 標(biāo)簽的 value 屬性是 String 類型引起的,凡是非 Object 類型的標(biāo)簽屬性的值,是不會被當(dāng)做一個 OGNL 表達(dá)式來處理的,
          除非你使用了 %{ expression } 語法,執(zhí)行時環(huán)境才會將 expression 當(dāng)做是一個 OGNL 表達(dá)式來處理。
          只有當(dāng)你理解了上面的2個案例,你才能正確的使用 OGNL 表達(dá)式。
          實際上規(guī)則非常簡單,當(dāng)標(biāo)簽屬性的類型為 Object 類型時,標(biāo)簽屬性的值就會被當(dāng)做是一個 OGNL 表達(dá)式來處理,因此可省略 %{} ;
          當(dāng)標(biāo)簽屬性的類型為 String 類型時,除非你使用了 %{ } 語法告訴執(zhí)行時環(huán)境這是一個 OGNL 表達(dá)式,否則,標(biāo)簽屬性的值會被當(dāng)做是一個普通的字符串來處理。

          文章示例源碼下載

          struts-ognl.zip




            
          posted on 2014-03-17 20:04 fancydeepin 閱讀(4783) 評論(5)  編輯  收藏

          評論:
          # re: Struts2 OGNL 表達(dá)式 2014-03-18 08:53 | 鵬達(dá)鎖業(yè)
          支持博主分享、、、、、、、、、、、、、  回復(fù)  更多評論
            
          # re: Struts2 OGNL 表達(dá)式 2014-03-19 09:17 | 零柒鎖業(yè)

          支持博主分享  回復(fù)  更多評論
            
          # re: Struts2 OGNL 表達(dá)式 2014-03-19 10:22 | 乳酸菌
          辛苦了。謝謝分享  回復(fù)  更多評論
            
          # re: Struts2 OGNL 表達(dá)式 2014-03-19 10:24 | 金利鎖業(yè)
          期待更新啊  回復(fù)  更多評論
            
          # re: Struts2 OGNL 表達(dá)式 2014-04-16 17:11 | 鋁板
          謝謝分享,辛苦了  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           

          隨筆分類(8)

          隨筆檔案(104)

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1462073
          • 排名 - 15

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 白河县| 江门市| 清徐县| 阿拉善右旗| 安徽省| 慈溪市| 大理市| 赫章县| 昌图县| 翁牛特旗| 凤庆县| 常宁市| 繁昌县| 沁阳市| 井研县| 长丰县| 台东市| 金门县| 达拉特旗| 昭通市| 鄄城县| 滨海县| 河北区| 兴安县| 德清县| 西青区| 东莞市| 分宜县| 健康| 安陆市| 大丰市| 富川| 万山特区| 合江县| 长顺县| 无极县| 瓦房店市| 红河县| 金塔县| 阿坝| 承德县|