Sturts2中的OGNL


参考http://struts.apache.org/2.x/docs/ognl-basics.html 和 http://struts.apache.org/2.x/docs/ognl.html
OGNL——Object Graph Navigation Language,参考 http://www.ognl.org/
一.Xwork的OGNL
在Struts2里边的OGNL是基于XWork的。XWork的OGNL和普通意义上的OGNL有一些差别,首先最大的差别就是OGNL只提供了一个根对象(root),而Xwork提供了一个ValueStack,这是Struts2的OGNL的默认root。另外,XWork提供了自己独特的OGNL PropertyAccessor自动从顶向下的查找Stack中符合条件的对象属性。
比如说,有两个对象Animal和Person,两个对象都提供了name属性,同时Animal有species属性,Person有salary属性。假定Animal在stack的顶端。

species // call to animal.getSpecies() 

salary // call to person.getSalary() 

name // call to animal.getName() because animal is on the top


从这里可以看到从顶向下查找的作用。在XWork中,我们可以用[n].name这种方式来访问不同层次的同名属性。n必须是正整数。

[0].name // call to animal.getName() 
[1].name // call to person.getName()


访问对象的静态属性的时候,OGNL默认采用如下的方式

@some.package.ClassName@FOO_PROPERTY 
@some.package.ClassName@someMethod()


而XWork访问静态属性的方式有所差异:通过@vs来访问。vs表示的意思是valueStack。并且,可以在vs后面跟随数字来表示其访问stack的层次。

@vs@FOO_PROPERTY 
@vs@someMethod() 

@vs1@FOO_PROPERTY 
@vs1@someMethod() 

@vs2@BAR_PROPERTY 
@vs2@someOtherMethod()


二.Struts2中的OGNL
在Struts2中,采用标准命名的上下文(Context)来处理OGNL表达式。处理OGNL的顶级对象是一个Map(也叫context map),而OGNL在这个context中就是一个顶级对象(root)。在用法上,顶级对象的属性访问,是不需要任何标记前缀的。而其它非顶级的对象访问,需要使用#标记。
Struts2框架把OGNL Context设置为我们的ActionContext。并且ValueStack作为OGNL的根对象。除value stack之外,Struts2框架还把代表application、session、request这些对象的Map对象也放到ActionContext中去。(这也就是Struts2建议在Action类中不要直接访问Servlet API的原因,他可以通过ActionContext对象来部分代替这些功能,以方便对Action类进行测试!)
Action的实例,总是放到value stack中。因为Action放在stack中,而stack是root(根对象),所以对Action中的属性的访问就可以省略#标记。但是,要访问ActionContext中其它对象的属性,就必须要带上#标记,以便让OGNL知道,不是从根对象,而是从其它对象中去寻找。
那么访问Action中的属性的代码就可以这样写

<s:property value="postalCode"/>
其它ActionContext中的非根对象属性的访问要像下面这样写:
<s:property value="#session.mySessionPropKey"/> or
<s:property value="#session['mySessionPropKey']"/> or
<s:property value="#request['myRequestPropKey']"/>

对Collection的处理,内容就很简单。
<s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />
这是处理List。这个代码在页面上建立一个下拉选项,内容是list中的内容,默认值是name2.
处理map

 <s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />

 需要注意的是,判断一个值是否在collection中。我们要使用in或者not in来处理。
<s:if test="'foo' in {'foo','bar'}">
   muhahaha
</s:if>
<s:else>
   boo
</s:else>

 另外,可以使用通配符来选择collection对象的子集。
 ?——所有匹配选择逻辑的元素
 ^——只提取符合选择逻辑的第一个元素
 $——只提取符合选择逻辑的最后一个元素
person.relatives.{? #this.gender == 'male'}

你可能感兴趣的:(Sturts2中的OGNL)