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. JDicom使用指南

    适用条件本指南用于使用JDicom进行环境模拟.产品调试. 一.安装JDicom运行JDicom安装程序之前,需安装JRE 1.3及以上版本.否则,弹出如下图所示报错 安装JRE 1.4:双击运行可执 ...

  2. EF中的那些批量操作

    在使用EF的过程中,我们经常会遇到需要批量操作数据的场景,批量操作有的时候不仅能提高性能,比如使用SqlBulkCopy进入批量插入的时候,而且比较方便操作,提高效率.那么这篇文章就来总结EF中的那些 ...

  3. Linux的五个查找命令(find、locate、whereis、which、type)

    1. find find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件. find的使用格式如下: $ find <指定目录> <指定条件> <指定动作> ...

  4. 使用AlarmManager设置闹钟----之二

    import android.media.MediaPlayer;import android.os.Bundle;import android.app.Activity;import android ...

  5. 铁人系列(2)LA2218

    思路:对于每个人  都会有n-1个半片面  加上x>0,y>0,1-x-y>0(这里的1抽象为总长) 代码是粘贴的  原来写的不见了  orz............ // LA22 ...

  6. Java中的深拷贝和浅拷贝

    1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...

  7. Spring中的Jdbc事务管理

    Spring提供了对事务的声明式事务管理,只需要在配置文件中做一些配置,即可把操作纳入到事务管理当中,解除了和代码的耦合. Spring声明式事务管理,核心实现就是基于Aop. Spring声明式事务 ...

  8. ie9,10 uploadify cleanUp bug

    起因:ie多次加载uploadify3.2版本这个组件的时候,出现了SCRIPT5007: 缺少对象.  From:http://blog.163.com/xiangfei209@126/blog/s ...

  9. bzoj 2440 简单莫比乌斯反演

    题目大意: 找第k个非平方数,平方数定义为一个数存在一个因子可以用某个数的平方来表示 这里首先需要考虑到二分才可以接下来做 二分去查找[1 , x]区间内非平方数的个数,后面就是简单的莫比乌斯反演了 ...

  10. C++二叉查找树实现及转化为双向链表

    二叉树首先要有树节点 template<class T> class BinaryNode { public: T element; BinaryNode *left; BinaryNod ...