OGNL
Ognl (Object-Graph Navigation Language)是对象图导航语言,用于访问一个容器中的对象的属性,调用对象的方法。主要是为了方便访问对象的属性和方法。
应用
- Struts2
- arthas中,命令参数
数据结构
OgnlContext是一个容器,本质是一个Map,key是String类型的值,value是对象。因此它具备所有Map的操作。
Ognl表达式,表达式由字符串组成,由Ognl解析,然后执行。
访问属性
OgnlContext中,分为root(根)节点和普通节点
实例属性
语法 #key.value
例子,ognlContext中有一个名为user的对象,它有一个name属性,那么访问该属性: #user.name
如果是根对象,不需要使用#
静态属性
语法 @全限定名@value
例子 @com.zzz.example.demo.Student@sex
赋值
使用=
号即可
调用方法
实例方法
语法 #key.method(param1,param2...)
例子 #stu.print("hello")
静态方法
语法 @全限定名@method(param1,param2...)
例子 @com.zzz.example.demo.Student@method1("hello")
操作符
- 逗号操作符:方法调用分隔参数、集合中分隔item、其余情况一条语句中的范围值是最后一个逗号后的语句的值
集合操作
构造
- 列表
{ null,"Untitled" }
- Map
#{ "foo" : "foo value", "bar" : "bar value" }
- 数组
new int[] { 1, 2, 3 }
访问
使用下标访问即可
语法 collection[index]
例子 listeners[0]
注意越界异常
投影
对集合中的所有元素执行相同的方法或者获取相同的属性,最后将结果组装为新的集合返回
语法 colltion.{ condition}
例子:
listeners.{delegate}
this在{}中表示当前变量
objects.{ #this instanceof String ? #this : #this.toString()}
选择
遍历集合,选择符合条件的对象,将结果组装成新的集合返回
语法 collection.{? condition}
例子
listeners.{? #this instanceof ActionListener}
选择第一个
collection.{? condition}[0]
但是选择的结果为空,然后抛越界异常
语法 collection.{^ condition}
将结果包装为集合返回
选择最后一个
collection.{$ condition}
将结果包装为集合返回
索引机制
- 如果是数组或者集合可以直接使用索引
myArray[0]
myList[0]
- 如果满足如下条件,表示这个属性拥有索引访问功能,可以这样使用
someProperty[2]
public PropertyType[] getPropertyName();
public void setPropertyName(PropertyType[] anArray);
public PropertyType getPropertyName(int index);
public void setPropertyName(int index, PropertyType value);
- 如果满足如下条件,则可以这样使用
session.attribute["foo"]
public PropertyType getPropertyName(IndexType index);
public void setPropertyName(IndexType index, PropertyType value);
例如
public Object getAttribute(String name);
public void setAttribute(String name, Object value)
官方文档
https://commons.apache.org/proper/commons-ognl/language-guide.html
本文简化了官方文档中的描述
例子
- 导包
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.0.6</version>
</dependency>
package com.zzz.example.demo;
import lombok.AllArgsConstructor;
import lombok.Data;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
/**
* @author example
* @description:
* @date 2020/11/24 3:34 下午
*/
public class OgnlTest {
//创建ognlContext
public OgnlContext getOgnlContext() {
OgnlContext context = (OgnlContext) Ognl.createDefaultContext(this);
return context;
}
//map操作,访问对象
public void testOgnlPropBase() throws OgnlException {
OgnlContext ognlContext = this.getOgnlContext();
ognlContext.put("a", "a");
ognlContext.put("b", "b");
ognlContext.setRoot("a");
System.out.println(ognlContext.entrySet());
Object expression = Ognl.parseExpression("#b");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
printClassAndValue(value);
}
public void testOgnlPropOne() throws OgnlException {
OgnlContext ognlContext = this.getOgnlContext();
Pen pen = new Pen(3, "red");
Stu stu = new Stu(18, "zuo", pen);
ognlContext.put("pen", pen);
ognlContext.put("stu", stu);
ognlContext.put("test", "T");
ognlContext.setRoot(pen);
Object expression = Ognl.parseExpression("color");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
printClassAndValue(value);
//逗号
expression = Ognl.parseExpression("#stu.name,#stu.age");
value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
printClassAndValue(value);
}
public void testOgnlMethod() throws OgnlException {
OgnlContext ognlContext = this.getOgnlContext();
Pen pen = new Pen(3, "red");
Stu stu = new Stu(18, "zuo", pen);
ognlContext.put("pen", pen);
ognlContext.put("stu", stu);
ognlContext.put("test", "T");
ognlContext.setRoot(this);
Object expression = Ognl.parseExpression("#stu.print(\"hello\")");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
System.out.println(value);
expression = Ognl.parseExpression("#pen.getColor().(#this+\"hhhhh\")");
value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
System.out.println(value);
}
public void testOgnlStaticProp() throws OgnlException {
OgnlContext ognlContext = this.getOgnlContext();
Pen pen = new Pen(3, "red");
Stu stu = new Stu(18, "zuo", pen);
ognlContext.put("pen", pen);
ognlContext.put("stu", stu);
ognlContext.put("test", "T");
ognlContext.setRoot(this);
Student student = new Student("liu", 20, pen);
Object expression = Ognl.parseExpression("@com.zzz.example.demo.Student@sex");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
printClassAndValue(value);
expression=Ognl.parseExpression("@com.zzz.example.demo.Student@method1(\"hello\")");
value=Ognl.getValue(expression,ognlContext,ognlContext.getRoot());
printClassAndValue(value);
}
private void printClassAndValue(Object value) {
if (value == null) {
System.out.println("fuck null");
}
System.out.println(value.getClass() + " " + value);
}
private void testArray() throws OgnlException {
OgnlContext ognlContext = this.getOgnlContext();
Object expression = Ognl.parseExpression("#a=1,#b=2,#c=3,{#a,#b,#c}");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
printClassAndValue(value);
}
public static void main(String[] args) throws OgnlException {
OgnlTest ognlTest=new OgnlTest();
ognlTest.testOgnlPropOne();
}
@Data
@AllArgsConstructor
class Stu {
int age;
String name;
Pen pen;
public void print(String fuck) {
System.out.println(fuck + " " + age + name + pen);
}
}
@Data
@AllArgsConstructor
class Pen {
int len;
String color;
public String getColor() {
return color;
}
}
}