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. js模拟快捷键操作表单

    <html> <head> </head> <body> <script> //键盘快捷键提交表单ctrl+s document.onkey ...

  2. mysql linux备份shell

    #!/bin/bash# export and backup the activity.sql  mysqldump  -uname -password activity --skip-lock-ta ...

  3. C#画线源码

    画线 private void Form1_Load(object sender, EventArgs e) { this.Paint += new PaintEventHandler(Form1_P ...

  4. [Jquery]网页定位导航特效

    描述:左右联动的导航,非常适合展示页面内容多,区块划分又很明显的,点击右边固定导航项时,左边的内容跟着切换.滑动滚动条的时候,右边的导航也随着左边的展示而进行高亮切换. 思路:比较滚动距离和楼层距离( ...

  5. bzoj 2241: [SDOI2011]打地鼠

    #include<cstdio> #include<iostream> using namespace std; ][],b[][],ans,sum; void pan(int ...

  6. ROS主题发布订阅

    节点是一个可执行程序,它连接到了ROS的网络系统中.我们将会创建一个发布者,也就是说话者节点,它将会持续的广播一个信息. 改变目录到之前所建立的那个包下: cd ~/catkin_ws/src/beg ...

  7. Zone.js

    https://github.com/angular/zone.js/ Zone.js

  8. Android Phonebook编写联系人UI加载及联系人保存流程(三)

    2014-01-07 09:54:13  将百度空间里的东西移过来. 本文从点击“添加联系人”Button开始,分析新建联系人页面UI是如何加载,以及新的联系人信息是如何保存的,借此,我们一探Phon ...

  9. NOIP2013 提高组day2 2 花匠 动规 找拐点 树状数组

    花匠 描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体 ...

  10. redis学习(一)

    一.redis简介 Redis是基于内存.可持久化的日志型.key-value高性能存储系统.关键字(Keys)是用来标识数据块.值(Values)是关联于关键字的实际值,可以是任何东西.有时候你会存 ...