OGNL 可以通过表达式从java对象中获取值或向java对象赋值。
Ognl.java 源码:
参数说明:
expression :Strig对象,
表达式 指明对root或context中的哪个属性或方法操作 (set or get or call)
Object root :任意一个java对象
从中取值或赋值,不以#开头的表达式,是对root取值或赋值
context :一个Map对象,
1.可以从中取值 以#开头的表达式是从context取值
2. 含Ognl的上下文对象(见addDefaultContext方法)
tree:一个Node对象
是Ognl.parseExpression(expression) 而生成的对象,即对表达式解析之后的对象
resultType:一个Class对象
期望的返回值类型,需要对获取的结果类型转换,
1.生成一个context (上下文对象)
/**
Ognl中有多个addDefaultContext方法,都是用来生成 context的
context 结构:
a.key=OgnlContext.CLASS_RESOLVER_CONTEXT_KEY,对应的是ClassResolver对象:自定义的加 载类,Ognl有默认的ClassResolver,如果ClassResolver不能加载类,就需要自定义的加载类。
b.key=OgnlContext.TYPE_CONVERTER_CONTEXT_KEY,对应的是TypeConverter对象:自定义类型 转换,Ognl有默认的类型转换TypeConverter,如果默认的转换不了,就需要指定自定义转换器
c.key=OgnlContext.MEMBER_ACCESS_CONTEXT_KEY,对应的是MemberAccess对象
d.key=OgnlContext.ROOT_CONTEXT_KEY,对应的是Root对象==参数root,getValue或 setValue方法中会把root保存在context中。
**/
public static Map addDefaultContext(Object root, ClassResolver classResolver,
TypeConverter converter, MemberAccess memberAccess, Map context)
{
OgnlContext result;
if (!(context instanceof OgnlContext)) {
result = new OgnlContext();
result.setValues(context);
} else {
result = (OgnlContext) context;
}
if (classResolver != null) {
result.setClassResolver(classResolver);
}
if (converter != null) {
result.setTypeConverter(converter);
}
if (memberAccess != null) {
result.setMemberAccess(memberAccess);
}
result.setRoot(root);
return result;
}
2.获取值:
/**
* Ognl有多个重载的getValue:
*getValue(String expression, Object root)
*getValue(String expression, Object root, Class resultType)
*getValue(Object tree, Object root, Class resultType)
*getValue(Object tree, Map context, Object root)
*getValue(String expression, Map context, Object root)
*getValue(String expression, Map context, Object root, Class resultType)
* 最终都调用下面这个方法
* 参数:<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; white-space: normal; background-color: #ffffff;">
* tree 由对表达式解析(Ognl.parseExpression(expression))而生成的对象
* context:上下文
</span>* root: 要操作的java对象
* resultType:结果要转换成为的类型
**/
public static Object getValue(Object tree, Map context, Object root, Class resultType)
throws OgnlException
{
Object result;
OgnlContext ognlContext = (OgnlContext) addDefaultContext(root, context);
Node node = (Node)tree;
if (node.getAccessor() != null)
result = node.getAccessor().get(ognlContext, root);
else
result = node.getValue(ognlContext, root);
if (resultType != null) {
result = getTypeConverter(context).convertValue(context, root, null, null, result, resultType);
}
return result;
}
3.赋值:
/**
* setValue 有多个重载方法,
* setValue(String expression, Object root, Object value)
* setValue(String expression, Map context, Object root, Object value)
* setValue(Object tree, Object root, Object value)
* setValue(Object tree, Map context, Object root, Object value)
* 最终都调用这个方法
* 参数:tree 由对表达式解析(Ognl.parseExpression(expression))而生成的对象
* value 要设定的值
* root 被赋值对象
*
**/
public static void setValue(Object tree, Map context, Object root, Object value)
throws OgnlException
{
OgnlContext ognlContext = (OgnlContext) addDefaultContext(root, context);
Node n = (Node) tree;
if (n.getAccessor() != null) {
n.getAccessor().set(ognlContext, root, value);
return;
}
n.setValue(ognlContext, root, value);
}
Ognl表达式语法:
http://commons.apache.org/proper/commons-ognl/language-guide.html
Ognl使用示例:
(如果一个表达式经常用到,最好先解析Ognl.parseExpression(expression),然后每次使用解析后的对象取值或赋值,这样更有效率)
public class OgnlTest {
@Test
public void testRootProperty(){
try{
String companyNameInit=" x company";
String companyNameNew=" y company";
Company company = new Company();
company.setCompanyName(companyNameInit);
Object root = company;
Object tree = Ognl.parseExpression("companyName");//表达式多次使用时,先编译比较好,供以后多次调用
String companyName = (String)Ognl.getValue(tree, root);//取root的属性
Assert.assertEquals(companyName, companyNameInit);
Ognl.setValue(tree, root, companyNameNew);//为companyName设置新值
companyName = (String)Ognl.getValue(tree, root);//取root的属性
Assert.assertEquals(companyName, companyNameNew);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testContextProperty(){
try{
Map context = new HashMap();
context.put("A", "A");
context.put("B", "B");
context.put("C", "C");
Object root = new Object();
String a = (String)Ognl.getValue("#A", context, root);
Assert.assertEquals("A", a);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testTypeConverter(){
try{
Company company = new Company();
company.setAsset(12000000);
Object root = company;
double assetD = (Double)Ognl.getValue("asset", root,Double.TYPE);//取root的属性,asset原来long型,使用类型转换为double
Assert.assertEquals(assetD, 12000000d);
Ognl.setValue("asset", root, 12.11f);//修改 asset 新值为float类型,会自动转换为Long型
long asset = (Long)Ognl.getValue("asset", root);//取root的属性asset
Assert.assertEquals(asset, 12);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testList(){
try{//数组,List set ognl 表达式格式相同
Company company = new Company();
company.setEmployeeNum(10);
List<Employee> employeeList = new ArrayList<Employee>();
company.setEmployeeList(employeeList);
for(int i=0;i<10;i++){
Employee employee = new Employee();
employee.setAge(i);
employeeList.add(employee);
}
Object root = company;
int age = (Integer)Ognl.getValue("employeeList[0].id",root);//获取LIST中元素的属性
Assert.assertEquals(0, age);
Ognl.setValue("employeeList[0].id", root, 99);//设置List元素中的属性
age = (Integer)Ognl.getValue("employeeList[0].id",root);
Assert.assertEquals(age, 99);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testMap(){
try{
Company company = new Company();
Map employeeMap = new HashMap();
Employee employee = new Employee();
employee.setAge(20);
employee.setId(100021);
employee.setName("yanlei");
employeeMap.put(employee.getName(), employee);
company.setEmployeeMap(employeeMap);
Object root = company;
Map context = new HashMap();
//#取root中的Map中的属性值,前提root得有getEmployeeMap()方法
int id = (Integer)Ognl.getValue("employeeMap.yanlei.id", context,root);//取root中employeeMap属性中的key=yanlei的Employee的id值
Assert.assertEquals(id, 100021);
Ognl.setValue("employeeMap.yanlei.id", root, 999);//修改ID的值
id = (Integer)Ognl.getValue("employeeMap.yanlei.id", context,root);//获取修改之后ID值
Assert.assertEquals(id, 999);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testCallMethod(){
try{
Company company = new Company();
company.setEmployeeNum(10);
List<Employee> employeeList = new ArrayList<Employee>();
company.setEmployeeList(employeeList);
for(int i=0;i<10;i++){
Employee employee = new Employee();
employeeList.add(employee);
}
Object root = company;
int employeeNum = (Integer)Ognl.getValue("employeeNum", root);
//方法调用
int employeeNum1 = (Integer)Ognl.getValue("employeeList.size()", root);//调用List.size()方法
Assert.assertEquals(employeeNum,employeeNum1);
Ognl.getValue("employeeList.remove(0)", root);//调用list.remove方法
employeeNum1 = (Integer)Ognl.getValue("employeeList.size()", root);
Assert.assertEquals(employeeNum-1,employeeNum1);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testCollection(){//
try{
List list = new ArrayList();
Set set = new HashSet();
char m = 'A';
Employee [] array = new Employee [10];
for(int i=0;i<10;i++){
Employee employee = new Employee();
employee.setAge(20+i);
employee.setName(m+"");
list.add(employee);
set.add(employee);
array[i]= employee;
m++;
}
HashMap root = new HashMap();
root.put("list",list);
root.put("set",set);
root.put("array",array);
Map context = new HashMap();
Object obj = Ognl.getValue("list.{name}", context,root);//提取List中所有元素的某个公用属性值,而生成新的集合ArrayList
System.out.println(obj.getClass()+":"+obj);//输出:java.util.ArrayList:[A, B, C, D, E, F, G, H, I, J]
obj = Ognl.getValue("set.{name}", context,root);//提取SET中所有元素的某个公用属性值,而生成新的集合ArrayList
System.out.println(obj.getClass()+":"+obj);//输出:class java.util.ArrayList:[F, E, D, B, A, J, I, G, C, H]
obj = Ognl.getValue("array.{name}", context,root);//提取数组中所有元素的某个公用属性值,而生成新的集合ArrayList
System.out.println(obj.getClass()+":"+obj);//输出:class java.util.ArrayList:[A, B, C, D, E, F, G, H, I, J]
int size = (Integer)Ognl.getValue("list.{? #this.age>20}.size()", context,root);//提取List中所有元素的age>20的所有元素,而生成新的集合ArrayList,再调用ArrayList.size
Assert.assertEquals(9, size);
String name = (String)Ognl.getValue("list.{^ #this.age>20}[0].name", context,root);//提取List中所有元素的age>20的第一个元素生成ArrayList,再获取它中唯一元素的name属性
Assert.assertEquals("B", name);
name = (String)Ognl.getValue("list.{$ #this.age>20}[0].name", context,root);//提取List中所有元素的age>20的最后一个元素生成ArrayList,再获取它中唯一元素的name属性
Assert.assertEquals("J", name);
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testMix() {
try{
Company company = new Company();
Map employeeMap = new HashMap();
Employee employee = new Employee();
employee.setId(100021);
employee.setName("x");
employeeMap.put(employee.getName(), employee);
company.setEmployeeMap(employeeMap);
Object root = company;
Map context = new HashMap();
context.put("x", "X 's address is m street ");
String address = (String)Ognl.getValue("#x", context,root);//取content(Map)中的key=x的对象
Assert.assertEquals(address, "X 's address is m street ");
//#取root中的Map中的属性值,前提root得有getEmployeeMap()方法
int id = (Integer)Ognl.getValue("employeeMap.x.id", context,root);//取root中employeeMap属性中的key=A的Employee的id值
Assert.assertEquals(id, 100021);
//表达式中的+号,分隔子表达式,ognl分别对子表达式取值,再连接
//常量的表示:字符串需要用单引号引起来。
String message = (String)Ognl.getValue("\'employee name is x, id:\'+employeeMap.x.id+', '+#x", context,root);//
Assert.assertEquals(message, "employee name is x, id:100021, X 's address is m street ");
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void testLogic(){
try{
Company company = new Company();
company.setAsset(1232);
company.setCompanyName("k company");
company.setEmployeeNum(200);
Object root = company;
Object obj = Ognl.getValue("(asset % 10 )== 2", root);
Assert.assertEquals(true, obj);
obj = Ognl.getValue("(asset % 10 )== 2", root);
Assert.assertEquals(true, obj);
obj = Ognl.getValue("asset > 100? 1:2", root);
Assert.assertEquals(1, obj);
obj = Ognl.getValue("asset = 1000", root);
Assert.assertEquals(1000, obj);
obj = Ognl.getValue("asset == 1000? 'success':'fail'", root);
Assert.assertEquals("success", obj);
obj = Ognl.getValue("asset > 1000 && employeeNum>100", root);
Assert.assertEquals(false, obj);
obj = Ognl.getValue("asset >= 1000 || employeeNum>=100", root);
Assert.assertEquals(true, obj);
obj = Ognl.getValue("8 & 0xE ", root);
Assert.assertEquals(8, obj);
obj = Ognl.getValue("8 | 0xE ", root);
Assert.assertEquals(14, obj);
obj = Ognl.getValue("8 ^ 0xE ", root);
Assert.assertEquals(6, obj);
obj = Ognl.getValue("~8", root);
Assert.assertEquals(-9, obj);
obj = Ognl.getValue("companyName=null", root);
Assert.assertEquals(null, obj);
obj = Ognl.getValue("companyName", root);
Assert.assertEquals(null, obj);
obj = Ognl.getValue("companyName != null", root);
Assert.assertEquals(false, obj);
obj = Ognl.getValue("companyName == null", root);
Assert.assertEquals(true, obj);
obj = Ognl.getValue("!(companyName == null)", root);
Assert.assertEquals(false, obj);
int m = 0xf;
}catch(Exception e){
e.printStackTrace();
}
}
}