OGNL使用小结(一)
最近一直使用struts2,表现层采用JSP,用的struts2标签,支持OGNL。 OGNL中的# $ %使用场景:
1、“#”主要有三种用途:
-
访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
名称
|
作用
|
例子
|
parameters
|
包含当前HTTP
请求参数的Map
|
#parameters.id[0]
作用相当于
request.getParameter("id")
|
request
|
包含当前
HttpServletRequest
的属性
(attribute)的Map
|
#request.userName相当于
request.getAttribute("userName")
|
session
|
包含当前
HttpSession的
属性(attribute)
的Map
|
#session.userName相当于
session.getAttribute("userName")
|
application
|
包含当前应用的
ServletContext
的属性(attribute)
的Map
|
#application.userName相当于
application.getAttribute("userName")
|
attr
|
用于按request >
session > application
顺序访问其属性
(attribute)
|
#attr.userName相当于
按顺序在以上三个范围(scope)
内读取userName属性,直到找到为止
|
-
用于过滤和投影(projecting)集合,如books.{?#this.price<100};
-
构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
2、“%”符号的用途
在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
[size=13px]<hr />
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']"
/></p>
<p><s:url value="%{#foobar['foo1']}"
/></p>
清单6 演示%用途的代码片段
3、“$”有两个主要的用途
-
用于在国际化资源文件中,引用OGNL表达式,例子请参考《在Struts 2.0中国际化(i18n)您的应用程序》
-
在Struts 2配置文件中,引用OGNL表达式,如 <action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action?albumId=${albumId}</result>
</action>
OGNL使用小结(二)
1、OGNL除了支持所有的Java操作符外,还支持以下几种:
1、逗号,
与C语言中的逗号操作符类似。
2、花括号{}
用于创建列表,元素之间用逗号分隔。
3、in和not in
用于判断一个值是否在集合中。
2、访问静态方法和静态字段
@class@method(args) //调用静态方法
@class@field //调用静态字段
其中class必须给出完整的类名(包括包名),如果省略class,那么默认使用的类是java.util.Math,如:
@@min(5,3)
@@max(5,3)
@@PI
3、索引访问
OGNL支持多种索引方式的访问。
1、数组和列表索引
在OGNL中,数组和列表可以大致看成是一样的。
如:array[0]、list[0]。表达式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
2、JavaBean的索引属性
要使用索引属性,需要提供两对setter和getter方法,一对用于数组,一对用于数组中的元素。
如:有一个索引属性interest,它的getter和setter如下
public String[] interest;
public String[] getInterest(){ return interest;}
public void setInterest(String[] interest){ this.interest=interest;}
public String getInterest(int i){ return interest[i]}
public void setInterest(int i, String newInterest){ interest[i]=newInterest;}
对于表达式interest[2],OGNL可以正确解释这个表达式,调用getInterest(2)方法。如果是设置的情况下,会调用setInterest(2,value)方法。
3、OGNL对象的索引属性
JavaBean的索引属性只能使用整型作为索引,OGNL扩展了索引属性的概念,可以使用任意的对象来作为索引。
4、对集合进行操作
1、创建集合:
创建列表
使用花括号将元素包含起来,元素之间使用逗号分隔。如{’zhangsan’,'lisi’,'wangwu’}
创建数组
OGNL中创建数组与Java语言中创建数组类似。
创建Map
Map使用特殊的语法来创建 #{”key”:value, ……}
如果想指定创建的Map类型,可以在左花括号前指定Map实现类的类名。如:
#@java.util.LinkedHashMap@{”key”:”value”,….}
Map通过key来访问,如map["key"]或map.key。
2、投影
OGNL提供了一种简单的方式在一个集合中对每一个元素闻调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称之为投影。
假如employees是一个包含了employee对象的列表,那么
#employees.{name}将返回所有雇员的名字的列表。
在投影期间,使用#this变量来引用迭代中的当前元素。
如:objects.{#this instanceof String? #this: #this.toString()}
3、选择
OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。
如#employees.{?#this.salary>3000}
将返回薪水大于3000的所有雇员的列表。
#employees.{^#this.salary>3000}
将返回第一个薪水大于3000的雇员的列表。
#employees.{$#this.salary>3000}
将返回最后一个薪水大于3000的雇员的列表。
5、lambda表达式
lambda表达式的语法是: :[...]。OGNL中的lambda表达式只能使用一个参数,这个参数通过#this引用。
如:
#fact= :[ #this<=1 ? 1 : #this* #fact ( #this-1) ], #fact(30)
#fib= :[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)
反应ognl特点的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
public class Root {
public static final String SIZE_STRING = "size";
private int[] array = { 1, 2, 3, 4 };
private Map map = new HashMap(23);
private List list = Arrays.asList(new Object[] { null, this, array });
public Root(){
map.put( "test", this );
map.put( "array", array );
map.put( "list", list );
map.put( "size", new Integer(5000) );
map.put( DynamicSubscript.first, new Integer(99) );
}
.......set,get方法
}
测试:
public class RootTest extends TestCase {
private OgnlContext context;
private static Root ROOT = new Root();
public void testProperties()throws Exception{
SimpleNode expression;
//直接用Root中map属性的名字来访问
expression = (SimpleNode) Ognl.parseExpression("map");
assertTrue(Ognl.getValue(expression, context, ROOT) == ROOT.getMap());
//访问Root中map属性的test属性
expression = (SimpleNode) Ognl.parseExpression("map.test");
assertTrue(Ognl.getValue(expression, context, ROOT).equals(ROOT));
//上面用map.test来访问,现在用下标形式访问
expression = (SimpleNode) Ognl.parseExpression("map[\"test\"]");
assertTrue(Ognl.getValue(expression, context, ROOT).equals(ROOT));
//跟上面的是一样的,这里演示了下标计算之后,访问到的值
expression = (SimpleNode) Ognl.parseExpression("map[\"te\" + \"st\"]"");
assertTrue(Ognl.getValue(expression, context, ROOT).equals(ROOT));
/*来看看对size的访问,这里有看头,在初始化的时候是map.put( "size", new Integer(5000) );
*很自然我们会想到用map.size或者map["size"]来访问,显然没有问题
*这里要演示的是,怎样访问静态变量,在Root中定义了:
*public static final String SIZE_STRING = "size";
*我们不可以用map[Root.SIZE_STRING]的形式访问吗?写成下面的形式:
*expression = (SimpleNode) Ognl.parseExpression("map[Root.SIZE_STRING]");
*OGNL就会认为有Root.SIZE_STRING这样一个对象是map的属性,而不是先去解释Root.SIZE_STRING为字符串size的
*看看下面是怎么办的,@做为静态导航
*/
expression = (SimpleNode) Ognl.parseExpression("map[@net.wide.ognl.bean.Root@SIZE_STRING]");
System.out.println(Ognl.getValue(expression, context, ROOT));
//下面通过下标访问List或者数组
expression = (SimpleNode) Ognl.parseExpression("map.array[0]");//map.list[1]
System.out.println(Ognl.getValue(expression, context, ROOT));
/*对DynamicSubscript的测试
* 先看看它的代码:
* switch (flag)
{
case FIRST: return "^";
case MID: return "|";
case LAST: return "$";
case ALL: return "*";
default: return "?"; // Won't happen
}
很清楚了!下面来试试
在Root中有这么一个初始化的地方:
map.put( DynamicSubscript.first, new Integer(99) );
我们通过OGNL表达式怎么访问呢?
对于一个数组或List应用上面的表达式,则是取出在这个列表中对应位置的元素
在Map中我们需要显示地使用DynamicSubscript.first等做为key才能取得到值
*/
expression = (SimpleNode) Ognl.parseExpression("map[^]");
System.out.println("first-^:" + Ognl.getValue(expression, context, ROOT));
expression = (SimpleNode) Ognl.parseExpression("map.array[|]");
System.out.println("middle-|:" + Ognl.getValue(expression, context, ROOT));
expression = (SimpleNode) Ognl.parseExpression("map.array[$]");
System.out.println("last-$:" + Ognl.getValue(expression, context, ROOT));
expression = (SimpleNode) Ognl.parseExpression("map.array[*]");
System.out.println("all-*:" + Ognl.getValue(expression, context, ROOT));
//测试数组或列表的伪属性
expression = (SimpleNode) Ognl.parseExpression("map.array.length");
System.out.println("array length:" + Ognl.getValue(expression, context, ROOT));
/* 看看下面有这么一个东东:
* map.(array[2] + size()).doubleValue()
* 在前面的学习中,我们了解了OGNL的导航链,解析链中的属性或方法都是基于当前解释出来的结果的
* 因此array[2]就是map.array[2]
* size()就是map.size()
* 他们相加转换成Double型。
* 看看结果是:8.0
*/
expression = (SimpleNode) Ognl.parseExpression("map.(array[2] + size()).doubleValue()");
System.out.println("map.(array[2] + size()).doubleValue():" + Ognl.getValue(expression, context, ROOT));
//map.(#this),this是对自身的引用,另外注意在变量名前加#符号,这个变量在这个表达式里面是全局的
expression = (SimpleNode) Ognl.parseExpression("map.(#this)");
System.out.println("map.(#this):" + Ognl.getValue(expression, context, ROOT));
//几个OGNL表达式,下面的意思是,测试map的第一个元素是否为空,如果为空则返回empty否则返回该对象
//这个写法我们非常熟悉,无论是java还是c都有这种写法
expression = (SimpleNode) Ognl.parseExpression("map[^].(#this == null ? 'empty' : #this)");
System.out.println("map[^].(#this == null ? 'empty' : #this):" + Ognl.getValue(expression, context, ROOT));
}
}
|