OGNL属性访问例子
作者:与风同行
前面是一些语法规则方面的东西,下面通过实际例子来看看:
例子来源于OGNL自带的测试用例,根据这些例子稍加改写而成,这些例子很经典,对属性访问的方方面面都有涉及
测试步骤:
1.建立下面的Root类,一个普通的javabean
package net.wide.ognl.bean; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import ognl.DynamicSubscript; import net.wide.test.MyMap; import net.wide.test.MyMapImpl; public class Root { public static final String SIZE_STRING = "size"; public static final int STATIC_INT = 23; private int[] array = { 1, 2, 3, 4 }; private Map map = new HashMap(23); private MyMap myMap = new MyMapImpl(); private List list = Arrays.asList(new Object[] { null, this, array }); private List settableList = new ArrayList(Arrays.asList(new Object[] { "foo", "bar", "baz" })); private int index = 1; private int intValue = 0; private String stringValue; private int yetAnotherIntValue = 46; private boolean privateAccessorBooleanValue = true; private int privateAccessorIntValue = 67; private int privateAccessorIntValue2 = 67; private int privateAccessorIntValue3 = 67; public String anotherStringValue = "foo"; public int anotherIntValue = 123; public int six = 6; 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) ); /* make myMap identical */ myMap.putAll( map ); } public int getAnotherIntValue() { return anotherIntValue; } public void setAnotherIntValue(int anotherIntValue) { this.anotherIntValue = anotherIntValue; } public String getAnotherStringValue() { return anotherStringValue; } public void setAnotherStringValue(String anotherStringValue) { this.anotherStringValue = anotherStringValue; } public int[] getArray() { return array; } public void setArray(int[] array) { this.array = array; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public int getIntValue() { return intValue; } public void setIntValue(int intValue) { this.intValue = intValue; } public List getList() { return list; } public void setList(List list) { this.list = list; } public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } public MyMap getMyMap() { return myMap; } public void setMyMap(MyMap myMap) { this.myMap = myMap; } public boolean isPrivateAccessorBooleanValue() { return privateAccessorBooleanValue; } public void setPrivateAccessorBooleanValue(boolean privateAccessorBooleanValue) { this.privateAccessorBooleanValue = privateAccessorBooleanValue; } public int getPrivateAccessorIntValue() { return privateAccessorIntValue; } public void setPrivateAccessorIntValue(int privateAccessorIntValue) { this.privateAccessorIntValue = privateAccessorIntValue; } public int getPrivateAccessorIntValue2() { return privateAccessorIntValue2; } public void setPrivateAccessorIntValue2(int privateAccessorIntValue2) { this.privateAccessorIntValue2 = privateAccessorIntValue2; } public int getPrivateAccessorIntValue3() { return privateAccessorIntValue3; } public void setPrivateAccessorIntValue3(int privateAccessorIntValue3) { this.privateAccessorIntValue3 = privateAccessorIntValue3; } public List getSettableList() { return settableList; } public void setSettableList(List settableList) { this.settableList = settableList; } public int getSix() { return six; } public void setSix(int six) { this.six = six; } public String getStringValue() { return stringValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public int getYetAnotherIntValue() { return yetAnotherIntValue; } public void setYetAnotherIntValue(int yetAnotherIntValue) { this.yetAnotherIntValue = yetAnotherIntValue; } } |
2.测试代码
package net.wide.ognl; import net.wide.test.Root; import ognl.DynamicSubscript; import ognl.Ognl; import ognl.OgnlContext; import ognl.SimpleNode; import junit.framework.TestCase; public class RootTest extends TestCase { private OgnlContext context; private static Root ROOT = new Root(); private static Object[][] TESTS = { { ROOT, "map", ROOT.getMap() }, { ROOT, "map.test", ROOT }, { ROOT, "map[/"test/"]", ROOT }, { ROOT, "map[/"te/" + /"st/"]", ROOT }, { ROOT, "map[(/"s/" + /"i/") + /"ze/"]", ROOT.getMap().get(Root.SIZE_STRING) }, { ROOT, "map[/"size/"]", ROOT.getMap().get(Root.SIZE_STRING) }, { ROOT, "map[@net.wide.ognl.bean.Root@SIZE_STRING]", ROOT.getMap().get(Root.SIZE_STRING) }, { ROOT.getMap(), "list", ROOT.getList() }, { ROOT, "map.array[0]", new Integer(ROOT.getArray()[0]) }, { ROOT, "map.list[1]", ROOT.getList().get(1) }, { ROOT, "map[^]", new Integer(99) }, { ROOT, "map[$]", null }, { ROOT.getMap(), "array[$]", new Integer(ROOT.getArray()[ROOT.getArray().length-1]) }, { ROOT, "[/"map/"]", ROOT.getMap() }, { ROOT.getArray(), "length", new Integer(ROOT.getArray().length) }, { ROOT, "getMap().list[|]", ROOT.getList().get(ROOT.getList().size()/2) }, { ROOT, "map.(array[2] + size()).doubleValue()", new Double(ROOT.getArray()[2] + ROOT.getMap().size()) }, { ROOT, "map.(#this)", ROOT.getMap() }, { ROOT, "map.(#this != null ? #this['size'] : null)", ROOT.getMap().get(Root.SIZE_STRING) }, { ROOT, "map[^].(#this == null ? 'empty' : #this)", new Integer(99) }, { ROOT, "map[$].(#this == null ? 'empty' : #this)", "empty" }, { ROOT, "map[$].(#root == null ? 'empty' : #root)", ROOT } }; protected void setUp() throws Exception { super.setUp(); context = (OgnlContext)Ognl.createDefaultContext(null); } protected void tearDown() throws Exception { super.tearDown(); } public void testProperties()throws Exception{ SimpleNode expression; //直接用Root中map属性的名字来访问 expression = (SimpleNode) Ognl.parseExpression((String) TESTS[0][1]); assertTrue(Ognl.getValue(expression, context, ROOT) == ROOT.getMap()); //访问Root中map属性的test属性 expression = (SimpleNode) Ognl.parseExpression((String) TESTS[1][1]); assertTrue(Ognl.getValue(expression, context, ROOT).equals(ROOT)); //上面用map.test来访问,现在用下标形式访问 expression = (SimpleNode) Ognl.parseExpression((String) TESTS[2][1]); assertTrue(Ognl.getValue(expression, context, ROOT).equals(ROOT)); //跟上面的是一样的,这里演示了下标计算之后,访问到的值 expression = (SimpleNode) Ognl.parseExpression((String) TESTS[3][1]); 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)); } } |