OGNL

OGNL ( Object Graph Navigation Language ),对象图导航语言。这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。 
在 Struts2 中,OGNL 需要和 Struts2 标签库配套来使用。

OGNL context


                               | -- application 
                               | 
                               | -- session 
                               | 
                               | -- value  stack ( root ) 
context  map  ---- | 
                               | -- request 
                               | 
                               | -- parameters 
                               | 
                               | -- attr ( searches page, request, session, then application scopes ) 
                               | 
Struts2 框架将 OGNL context 设置为我们的 ActionContext,并将 ValueStack 作为 OGNL 的根对象。而 Action 则置于 ValueStack 的最顶层。 
除此之外,Struts2 框架还把代表 application、request、session 对象的 Map 对象也放到 ActionContext 中,使得 Action 与 Servlet API 解耦。

名称 描述
ValueStack 值栈,作为 OGNL 上下文的根对象。通过 KEY 来访问,非根对象需要用 #KEY 来访问
parameters Map 类型,封装了请求中的所有参数。访问 #parameters.name 相当于调用 HttpServletRequest.getParameter( )
request Map 类型,封装了 request 对象中的所有属性。访问 #request.name 相当于调用 HttpServletRequest.getAttribute( )
session Map 类型,封装了 session 对象中的所有属性。访问 #session.name 相当于调用 HttpSession.getAttribute( )
application Map 类型,封装了 application 对象中的所有属性。访问 #application.name 相当于调用 ServletContext.getAttribute( )
attr Map 类型,依次从 page、request、session、application 对象中检索属性的值

OGNL 访问 Action 中的数据

Action 位于值栈的栈顶位置,而值栈又是 OGNL 的根对象,因此,在 OGNL 表达式中可直接使用属性名称来访问 Action 当中的数据。如: 
<s:property value="name" /> 
实际上,这里是通过调用 Action 当中的 getName( ) 方法来获取得到数据的,而不管 Action 当中是否有一个名称为 name 的属性变量。 
因此,如果需要在页面中获取得到 Action 当中的数据,你只需要为你的 Action 类编写 getXX( ) 方法就可以了。

测试环境

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 调用方法

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

OGNL 调用静态属性

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

OGNL 调用静态方法

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

OGNL 调用构造方法

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

OGNL 使用索引访问数组和列表

< 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 访问集合的伪属性

类型 伪属性 伪属性对应的 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 当前元素的索引
IteratorStatus first 当前元素是否是集合的第一个元素
IteratorStatus last 当前元素是否是集合的最后一个元素
IteratorStatus count 当前迭代元素的数量,count = index + 1
IteratorStatus even index + 1 是否为偶数
IteratorStatus odd index + 1 是否为奇数
< table > 
   < tr  align ="center" > 
     < td  width ="2%" >索引 </ td > 
     < td  width ="5%" >值 </ td > 
     < td  width ="8%" >当前迭代的数量 </ 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 投影

如果把集合中的数据想象成是数据库表中的数据,那么,投影就是从这张表中选取某一列所构成的一个新的集合。投影的语法:collection.{expression}

< s:property  value ="personList.{name}" />

OGNL 过滤

OGNL 过滤也称为选择,就是把满足 OGNL 表达式的结果选择出来构成一个新的集合。 
过滤的语法:collection.{?expression} 或 collection.{^expression} 或 collection.{$expression}

符号 作用
? 选取与逻辑表达式匹配的所有结果
^ 选取与逻辑表达式匹配的第一个结果
$ 选择与逻辑表达式匹配的最后一个结果
#this 代表当前迭代的元素
< 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 表达式的语法,这里的 %{ } 是 OGNL 表达式的语法。 
也许你开始困惑,上面示例不是都在使用 OGNL 表达式吗?!没见 %{ } 出现过啊!好眼力!凡是属于 OGNL 表达式的串,你都可以使用 %{ } 来将它们包裹住,但这不是必须的。例如 <s:property value="expression" /> 中的 expression 在任何时候都是被当做 OGNL 表达式来处理的。

< s:property  value ="subject" />   <!--  subject被OGNL进行表达式求值输出  --> 
< s:property  value ="i love java so much" />   <!--  什么都不输出  -->

第2行之所以什么都不输出,是因为执行时环境把 i love java so much 这个字符串也当做是一个 OGNL 表达式来处理了,但在 OGNL 上下文中并找不到与这个 KEY 对应的值,因此什么都没有输出。 
这是由于 <s:property /> 标签的 value 属性是 Object 类型引起的,凡是 Object 类型的标签属性的值,都会被当做是一个 OGNL 表达式来处理。 
这种情况下的解决办法是:使用单引号将它们引起来,表明这是一个普通的字符串,而不是 OGNL 表达式。

< s:property  value ="'subject'" />   <!--  输出 subject  --> 
< s:property  value ="'i love java so much'" />   <!--  输出 i love java so much  -->

再如 <s:textfield value="expression" /> 中的 expression 什么时候被当做 OGNL 表达式来处理就要取决于你是否使用了 %{ } 语法,如果使用了,那么它就是一个 OGNL 表达式,如果没有使用,那么它就只是一个普通的字符串而已。

< s:textfield  value ="author" />          <!--  author被当做普通字符串原样输出  --> 
< s:textfield  value ="%{author}" />       <!--  author被OGNL进行表达式求值输出  --> 
< s:textfield  value ="person.name" />     <!--  person.name被当做普通字符串原样输出  --> 
< s:textfield  value ="%{person.name}" />  <!--  person.name被OGNL进行表达式求值输出  -->

这是由于 <s:textfield /> 标签的 value 属性是 String 类型引起的,凡是非 Object 类型的标签属性的值,是不会被当做一个 OGNL 表达式来处理的, 
除非你使用了 %{ expression } 语法,执行时环境才会将 expression 当做是一个 OGNL 表达式来处理。 
只有当你理解了上面的2个案例,你才能正确的使用 OGNL 表达式。 
实际上规则非常简单,当标签属性的类型为 Object 类型时,标签属性的值就会被当做是一个 OGNL 表达式来处理,因此可省略 %{} ; 
当标签属性的类型为 String 类型时,除非你使用了 %{ } 语法告诉执行时环境这是一个 OGNL 表达式,否则,标签属性的值会被当做是一个普通的字符串来处理。

Struts2 OGNL使用详解(转)的更多相关文章

  1. struts2常用标签详解(申明:来源于网络)

    struts2常用标签详解(申明:来源于网络) 地址:http://blessht.iteye.com/blog/1184960

  2. struts2基本配置详解2

    接上篇struts2基本配置详解,还有一些配置没有讲到,下面将继续. struts.xml <package name="com.amos.web.action" names ...

  3. struts2标签库详解

    要在jsp中使用Struts2的标志,先要指明标志的引入.通过jsp的代码的顶部加入以下的代码: <%@taglib prefix="s" uri="/struts ...

  4. Struts2的OGNL标签详解

    一.Struts2可以将所有标签分成3类: UI标签:主要用于生成HTML元素的标签. 非UI标签:主要用于数据库访问,逻辑控制等标签. Ajax标签:用于Ajax支持的标签. 对于UI标签,则有可以 ...

  5. Struts2 标签库详解2

    Struts2标签库 包括: OGNL Struts2标签分类 控制标签 :(if, elseif,else, iterator, append, merge, generator, subset, ...

  6. 关于Struts2的类型转换详解

    详细出处参考:http://www.jb51.net/article/35465.htm 一.类型转换的意义 对于一个智能的MVC框架而言,不可避免的需要实现类型转换.因为B/S(浏览器/服务器)结构 ...

  7. Struts2值栈详解

    1. 关于值栈: 1). helloWorld 时, ${productName} 读取 productName 值, 实际上该属性并不在 request 等域对象中, 而是从值栈中获取的.  2). ...

  8. struts2各个功能详解(1)----参数自动封装和类型自动转换

    struts2里面的各个功能,现在确实都不清楚,完全属于新学! 通过前面的例子,有时就会疑问,这些jsp中的数据信息是怎么传送给action的?例如: <form action = " ...

  9. Struts2 标签库详解

    Struts2标签库 包括: OGNL Struts2标签分类 控制标签 :(if, elseif,else, iterator, append, merge, generator, subset, ...

随机推荐

  1. 分形树Fractal tree介绍——具体如何结合TokuDB还没有太懂,先记住其和LSM都是一样的适合写密集

    在目前的Mysql数据库中,使用最广泛的是innodb存储引擎.innodb确实是个很不错的存储引擎,就连高性能Mysql里都说了,如果不是有什么很特别的要求,innodb就是最好的选择.当然,这偏文 ...

  2. go局部变量的存储空间是堆还是栈?

    编译器会自动选择在栈上还是在堆上分配局部变量的存储空间,但可能令人惊讶的是,这个选择并不是由用var还是new声明变量的方式决定的. var global *int func f() { var x ...

  3. [转载]linux下svn常用指令

    一下内容转载于:http://blog.chinaunix.net/space.php?uid=22976768&do=blog&id=1640924.这个总结的很好~ windows ...

  4. FZU 2093 找兔子 状压DP

    题目链接:找兔子 n的范围是[1, 15],可以用0 到 (1<<n)-1 的数表示全部状态,用dp[i] = t表示到达状态i的最少时间是t,对于每个点,如果它能到达的所有点在t秒时都已 ...

  5. [原创]checkstyle下载与安装

    checkstyle是一款功能很强的java静态代码检查工具,为eclipse的插件.在网上看了,大致有两种安装方法.第一种 为联网,在eclipse里输入URL下载:另一种为下载好插件后,离线安装. ...

  6. 一模 (3) day2

    第一题: 题目大意:和day1一样,给出m个小于n的数,求出出现次数大于m div 2 的数. 数据范围加大,1<=n<=2^31   1<=m<=3000000 解题过程: ...

  7. BindingNavigator操作DatagridView的数据

    参考 http://wenku.baidu.com/link?url=NWfEfArPZvDO_aI-xEKBHVGoZY9wQO_Oty_GCsGLiPspheCzFYLf_dytuWAqN2_0A ...

  8. Codeforces Round #326 (Div. 2)-Duff and Meat

    题意: Duff每天要吃ai千克肉,这天肉的价格为pi(这天可以买好多好多肉),现在给你一个数值n为Duff吃肉的天数,求出用最少的钱满足Duff的条件. 思路: 只要判断相邻两天中,今天的总花费 = ...

  9. xlistview的(java)

    package com.bwie.xlistviews; import java.text.SimpleDateFormat;import java.util.Date; import com.bwi ...

  10. Java基础01 ------ 从HelloWorld到面向对象

    Java是完全面向对象的语言.Java通过虚拟机的运行机制,实现“跨平台”的理念.我在这里想要呈现一个适合初学者的教程,希望对大家有用. "Hello World!" 先来看一个H ...