`

OGNL的使用

 
阅读更多

 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)
* 最终都调用下面这个方法
*  参数:
*               tree 由对表达式解析(Ognl.parseExpression(expression))而生成的对象
*               context:上下文
*       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();
			}
	}
}

 

 

 

分享到:
评论

相关推荐

    ognl表达式java使用案例详解(测试通过)

    本案例提供ognl使用详解,测试通过,只需解压放入自己WEB项目中,执行struts_ognl包内java文件即可(未提供jia包,若需要可以联系留言发至邮箱),若测试不好可以联系本人提供指导. Struts 2默认的表达式语言是OGNL...

    OGNL使用小结

    本篇文章将详细总结OGNL的使用技巧。 首先,`#`符号在OGNL中有三个主要用途。一是访问OGNL上下文和Action上下文,比如`#parameters`、`#request`、`#session`和`#application`分别对应HTTP请求的参数、请求属性、...

    struts2中OGNL使用源自javaWeb编程王者归来

    在这个实例中,我们将深入探讨如何在Struts2中使用OGNL来获取Servlet对象的值、筛选集合中的对象,以及理解OGNL表达式的生命周期。 首先,让我们了解OGNL的基本语法。OGNL允许我们通过点号(.)和方括号([])来...

    使用的ognl的chm

    - Struts2和Hibernate的官方文档中也有关于OGNL使用的部分。 - 在线教程和博客文章可以帮助理解OGNL的实际应用场景和最佳实践。 总结起来,OGNL是Java开发中的强大工具,特别是在Web框架中,它简化了对象交互和数据...

    Struts2 的OGNL使用简介

    本篇文章将详细介绍Struts2中OGNL的使用,包括基本语法、表达式操作以及在实际开发中的应用。 ### OGNL简介 OGNL是一种强大的表达式语言,允许动态地访问和修改对象图。在Struts2中,OGNL负责视图层和模型层之间的...

    ognl-2.6.11.jar 官方源码

    3. **上下文映射**:OGNL使用一个上下文映射(Context Map),其中存储了变量和对象,使得表达式可以引用这些变量和对象,无需显式传递。 4. **列表和数组索引**:可以直接通过索引来访问列表和数组元素,如`list[0...

    ognl源码

    为了提高性能,OGNL使用了缓存机制。解析后的AST节点和求值结果会被缓存,当遇到相同的表达式时,可以直接从缓存中获取,避免了重复解析和求值。 **6. OGNL的安全性** 虽然OGNL的强大功能使其在很多场景下非常有用...

    ognl-2.7.3-src

    OGNL 使用上下文对象来存储变量和值,而值栈则用于处理表达式中的运算对象。源码揭示了上下文和值栈如何协同工作,以处理表达式中的变量引用和运算。 8. **OGNL 在实际应用中的作用** OGNL 广泛应用于许多 Java ...

    OGNL静态方法定义

    4. `OgnlContext`:这是OGNL使用的特殊上下文类,它扩展了标准的Java `Map`接口,提供了一些额外的功能,如自动类型转换、变量注册等。 5. `@`符号在OGNL中的使用:在OGNL表达式中,`@`符号用来引用对象。例如,`@...

    ognl项目文件和源代码

    2. **上下文(Context)**: OGNL使用一个上下文对象来存储变量和方法调用结果,这在处理复杂逻辑时非常有用。 3. **栈(Stack)**: OGNL表达式的计算基于一个栈模型,它将操作数和结果压入栈中,执行操作并弹出结果。 ...

    ognl源码.rar

    3. **上下文(Context)与栈(Stack)**:在解析和执行表达式时,OGNL使用上下文存储变量和对象,而栈则用于存储表达式的中间结果和最终结果。 ### OGNL的关键特性 1. **动态类型**:OGNL是动态类型的,这意味着它...

    OGNL jar包及源码

    2. **上下文(Context)**: OGNL使用一个Map结构作为上下文,存储变量和对象,使得在表达式中可以直接引用这些变量。 3. **值引出(GetValue)与值设定(SetValue)**: OGNL能方便地获取或设置对象的属性,即使这些属性是...

    ognl.zip_ognl

    3. **值解析器(Value Extractor)**:OGNL使用值解析器来访问对象的属性,支持标准的JavaBeans规范,以及自定义的访问策略。 4. **表达式缓存**:为了提高性能,OGNL会缓存已解析的表达式,避免重复计算。 5. **...

    ognl源代码,最新版本

    - OGNL使用类似于JavaScript的语法,但它是为Java设计的,可以无缝地集成到Java代码中。 2. OGNL的主要特性: - 属性导航:可以直接通过"."符号访问对象的属性,例如`person.name`。 - 方法调用:可以调用对象的...

    Struts2 OGNL示例(Maven项目)

    这个"Struts2 OGNL示例(Maven项目)"提供了使用OGNL与Struts2集成的实例,帮助开发者更好地理解和应用这一强大的特性。 首先,让我们了解什么是OGNL。OGNL是一种强大的表达式语言,允许我们访问和修改对象图中的...

    OGNL符号的使用

    OGNL 符号的使用 OGNL(Object-Graph Navigation Language)是一种可以方便地操作对象属性的开源表达式语言。它有很多特点,例如支持对象方法调用、类静态的方法调用和值访问、赋值操作和表达式串联、访问 OGNL 上...

    OGNL表达式的使用及文档

    本篇将详细介绍OGNL的使用方法及其核心概念。 一、OGNL的基础知识 1. **表达式语法**:OGNL表达式通常由对象名、点号和属性名组成,例如`user.name`,表示获取`user`对象的`name`属性。也可以通过索引访问集合元素...

    OGNL网上资料整理

    OGNL使用变量上下文来存储临时变量和作用域内的值,方便在表达式中引用。 3.2 自定义转换器和类型处理器 开发者可以通过注册自定义的转换器和类型处理器,扩展OGNL对特定类型的处理能力。 3.3 安全性考虑 在生产...

    struts2 ognl源码

    - OGNL使用`ValueAccessor`接口来访问对象的属性。不同的类型(如POJO、Map等)有不同的访问器实现。 - 当表达式涉及到方法调用时,OGNL会调用`MethodAccessor`来执行方法。 3. **OGNL上下文(Context)**: - ...

Global site tag (gtag.js) - Google Analytics