OGNL概述
定义
- OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL作为默认的表达式语言。
特性
- Ognl有三个核心类,Ognl,OgnlContext,OgnlRuntime
- Ognl:Ognl的核心操作类,封装多种函数。解析表达式,生成上下文,以及提取表达式中的内容等
- OgnlContext:是Ognl的上下文环境,本质是一个Map,存储需要被表达式解析提取的数据。
- OgnlRuntime:可理解为Ognl的配置类,提供多种配置和接口,实现Ognl的自定义特性
- 此外OgnlContext能设置根(Root)元素,当设置根元素时,取值不需要添加#,mybatis框架中#{}表达式中的Ognl表达式正是用到了根元素
案例
Ognl表达式取值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void testOGNL() throws OgnlException { Student student = new Student(); student.setName("ypjiao"); student.setId(1); OgnlContext ognlContext = new OgnlContext(); ognlContext.put("student",student); Object value = Ognl.getValue("#student.name", ognlContext, ognlContext.getRoot()); out.println(value); Object expression = Ognl.parseExpression("#student.id"); Object value1 = Ognl.getValue(expression, ognlContext, ognlContext.getRoot()); out.println(value1); }
|
Ognl表达式获取Root元素
1 2 3 4 5 6 7 8
| Student student = new Student(); student.setName("ypjiao"); OgnlContext ognlContext = new OgnlContext();
ognlContext.setRoot(student);
Object value = Ognl.getValue("name", ognlContext, ognlContext.getRoot()); out.println(value);
|
Ognl表达式创建数组和对象
1 2 3 4 5 6 7
| OgnlContext ognlContext = new OgnlContext(); Object expression = Ognl.parseExpression("{'aaa','bbb','ccc'}");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot()); out.println("array="+value);
|
Ognl调用静态方法
1 2 3 4
| OgnlContext ognlContext = new OgnlContext(); Object expression = Ognl.parseExpression("@Math@random()"); Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot()); out.println("random="+value.toString());
|
Ognl调用方法
1 2 3 4 5 6 7
| Student student = new Student(); student.setName("Andrew"); OgnlContext ognlContext = new OgnlContext(); ognlContext.put("student_Andrew",student); Object expression = Ognl.parseExpression("#student_Andrew.getName()"); Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot()); out.println("name="+value.toString());
|
其它特性
Property访问器
我们可以注册自定义解析器以及解析对象,用于解析特殊的数据或达到解析自定义。当注册完成后,Ognl在解析数据时当发现有注册过的对象类型,则会调用专门的解析器的get方法来读取数据;
我们需要分别实现解析器和解析对象
解析器
- 解析器需要实现PropertyAccessor接口
- 实现接口中的方法来达到自定义
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
| class YpAccessor implements PropertyAccessor{ @Override public Object getProperty(Map map, Object target, Object o1) throws OgnlException { Map ypMap = (Map)target; Object parameterObject = ypMap.get("test_ypjiao"); if (parameterObject instanceof Map) { return ((Map)parameterObject).get(o1); } return parameterObject; }
@Override public void setProperty(Map map, Object target, Object o1, Object o2) throws OgnlException { Map<String,Object> ypMap = (Map<String,Object>)target; ypMap.put((String)o1,o2); }
@Override public String getSourceAccessor(OgnlContext ognlContext, Object o, Object o1) { return null; }
@Override public String getSourceSetter(OgnlContext ognlContext, Object o, Object o1) { return null; } }
|
解析对象
解析类型一般是一个集合,完全自定义,他们最终会作为参数传递给解析器的get或set方法以便调用;
我们可以通过第二个参数获取到解析类型对象,本例中解析对象是一个继承自HashMap的集合
1 2
| class YpMap extends HashMap { }
|
案例调用
- 需要新的解析对象时,都应该注册
- 本例中会将实体对象Student存入自定义集合YpMap中,且key为一个写死的固定值,不会从表达式中获取和传输这个固定值,目的是为了让自定义的解析器通过写死的key获取到我们需要的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void testOGNLArray() throws OgnlException { OgnlRuntime.setPropertyAccessor(YpMap.class,new YpAccessor());
YpMap ypMap = new YpMap(); Student student = new Student(); student.setName("ypjiao"); student.setId(1); ypMap.put("test_ypjiao", student); Map ognlContext = Ognl.createDefaultContext(ypMap, new DefaultClassResolver(), new DefaultTypeConverter(), new DefaultMemberAccess(true)); Object value = Ognl.getValue("student.name", ognlContext, ypMap); out.println("name="+value); }
|