Ognl表达式引擎

Ognl框架
1说明:Struts2只是把Ognl作为它的表达式引擎,此文章SAMPLE只是单独的Ognl框架,与struts2没有任何联系
2.能力有限,代码中注释难免有误请包含或指证
3.目的:分享, 可作为"数据流转"入口
4.内容:以下为主代码内容,javaBean(User和Company)就不贴出来了,看代码里的setter就可以构造出javaBean了

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

/**

  • 引入jar包:ognl.jar +javassist.jar

  • OGNL表达式引擎

  • 1.表达式引擎作用:

  • 2.数据流转

  •  表达式引擎应用场景:略
    
  • 3.设计模式:类似策略模式/监听器模式

  •  	根据root类型,指定具体的PropertyAccessor
    
  •  比如,root为List则指派ListPropertyAccessor处理相应逻辑
    
  •  	root为Array则指派ArrayPropertyAccessor处理相应逻辑
    
  • 4.调用层次:Ognl
    Node
    SimpleNode
    ASTProperty
    SimpleNode
    OgnlRuntime
    PropertyAccessor{ Object getProperty(Map context, Object target, Object name)}

  • 5.JJTree 一个有意思的东西,有兴趣的可以看看

  • @author 拈花为何不一笑

  • @since 8/23/2018

*/
public class OgnlExpressEngine {

/**
* 单元测试
*/
public static void main(String[] args) {

// testOgnlForObj();
// testOgnlForMap();
// testOgnlForList();
testOgnlForArray();

  	System.exit(0);
}


/**
 * Ognl访问数组
 * 	访问数组元素rootInt[2],如何使用Ognl中的方法getValue呢
 * 		猜想了下expression处,用[2]代替,
 * 			Ognl.getValue(expression, context,root);果真对了。
 * 	其它类似,比如map,list,set,obj平常你怎么访问它们的就试着写expression
 * 
 * 	源码片段:
 * 		 if (index instanceof Number)
            {
                int i = ((Number) index).intValue();

                result = (i >= 0) ? Array.get(target, i) : null;
            } else
            {
                throw new NoSuchPropertyException(target, index);
            }
 */
private static void testOgnlForArray() {
	int[] rootInt = new int[]{1,3,56,8,10};
	
	OgnlContext context = new OgnlContext() ;
	context.put("rootInt", rootInt);
	context.setRoot(rootInt);
	
	Object result = null;
	try {
		
		result = Ognl.getValue("[2]", context,rootInt);
		System.out.println("Ognl访问数组中的元素:" + result);
		
		//使用DynamicSubscript访问Array
		// [^] 表示list中的第一个元素, [$] 表示list中的最后一个元素, [|] 表示list中的中间元素, and [*]表示所有元素
		Object firstElemet = Ognl.getValue("[^]", context,rootInt);
		Object lastElement = Ognl.getValue("[$]", context,rootInt);
		Object midElement = Ognl.getValue("[|]", context,rootInt);
		Object allElement = Ognl.getValue("[*]", context,rootInt);
		
		System.out.println("firstElemet:" + firstElemet + "\n"
						+ "lastElement:" + lastElement + "\n"
						+ "midElement:" + midElement + "\n"
						+ "allElement:" + allElement + "\n"
		);
		System.out.println("Array工具操作数据对象allElement:" + Array.getInt(allElement, 2));
		
		//数组中的嵌套,带大家弄个好玩的初始化对象数组
		User[] users = { new User(){
						{setId(6661);setName("洪宇");}
					},
					new User(){
						{setId(6662);setName("洪宙");}
					}};
		OgnlContext context2 = new OgnlContext();
		context2.put("users", users);
		context2.setRoot(users);
		Object firtElement_id = Ognl.getValue("[0].id", context2, context2.getRoot());
		Object firtElement_name = Ognl.getValue("[0].name", context2, context2.getRoot());
		Object secondElement_id = Ognl.getValue("[1].id", context2, context2.getRoot());
		Object secondElement_name = Ognl.getValue("[1].name", context2, context2.getRoot());
		System.out.println("Ognl访问数组中的嵌套元素:\n" 
					+ "firtElement_id: " + firtElement_id  +", firtElement_name: "+ firtElement_name + "\n"
					+ "secondElement_id: " + secondElement_id  +", secondElement_name: " + secondElement_name + "\n"
			);
		
	}catch (OgnlException e) {
		e.printStackTrace();
	}
	
}

/**
 * Ognl访问List集合
 * 	
 * 遇到异常(很眼熟吧):
 * 	ognl.ParseException: Encountered "" at line 1, column 3.
		Was expecting one of:
	    ":" ...
	    "not" ...
	    "+" ...
	    "-" ...
	    "~" ...
	    "!" ...
	    "(" ...
	    "true" ...
	    "false" ...
	    "null" ...
	    "#this" ...
	    "#root" ...
	    "#" ...
	    "[" ...
	    "{" ...
	    "@" ...
	    "new" ...
	     ...
	     ...
	    "\'" ...
	    "`" ...
	    "\"" ...
	     ...
	     ...
	   
	  原因:断点时用到inspect查看表达式的值时抛出异常,位于Ognl的parseExpression方法
	  	中的表达式:return parser.topLevelExpression();
	  解决方案:在此调试中的表达式处,不使用MyEclipse inspect就OK了
	
	源码片段:
		 if (name instanceof String) {
        Object result = null;

        if (name.equals("size")) {
            result = new Integer(list.size());
        } else {
            if (name.equals("iterator")) {
                result = list.iterator();
            } else {
                if (name.equals("isEmpty") || name.equals("empty")) {
                    result = list.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
                } else {
                    result = super.getProperty(context, target, name);
                }
            }
        }

        return result;
    }
    
		if (name instanceof Number)
        return list.get(((Number) name).intValue());
		
 */
private static void testOgnlForList() {
	
	//list中简单元素
	List rootList = new ArrayList();
	rootList.add("hello");
	rootList.add("tomson");
	rootList.add("and you");
	
	OgnlContext context = new OgnlContext() ;
	context.put("rootList", rootList);
	context.setRoot(rootList);
	
	Object result = null;
	try {
		
		result = Ognl.getValue("[0]", context,rootList);
		System.out.println("Ognl访问list中的元素: " + result);
		
		//使用DynamicSubscript访问List
		// [^] 表示list中的第一个元素, [$] 表示list中的最后一个元素, [|] 表示list中的中间元素, and [*]表示所有元素
		Object firstElemet = Ognl.getValue("[^]", context,rootList);
		Object lastElement = Ognl.getValue("[$]", context,rootList);
		Object midElement = Ognl.getValue("[|]", context,rootList);
		Object allElement = Ognl.getValue("[*]", context,rootList);
		System.out.println("firstElemet:" + firstElemet + "\n"
						+ "lastElement:" + lastElement + "\n"
						+ "midElement:" + midElement + "\n"
						+ "allElement:" + allElement + "\n"
		);

		
	} catch (OgnlException e) {
		e.printStackTrace();
	}
	
	//2.list嵌套元素
	User user1 = new User();
	user1.setId(9527);
	user1.setName("周星星");
	
	User user2 = new User();
	user2.setId(9528);
	user2.setName("刘德华");
	
	List list = new ArrayList();
	list.add(user1);
	list.add(user2);
	
	OgnlContext context2 = new OgnlContext();
	context2.put("list", list);
	context2.setRoot(list);
	
	Object result1;
	Object firstResult_id;
	Object firstResult_name;
	Object secondResult_id;
	Object secondResult_name;
	try {
		 result1 = Ognl.getValue("size", context2, context2.getRoot());
		 
		 firstResult_id = Ognl.getValue("[0].id", context2, context2.getRoot()); 
		 firstResult_name = Ognl.getValue("[0].name", context2, context2.getRoot());
		 
		 secondResult_id = Ognl.getValue("[1].id", context2, context2.getRoot()); 
		 secondResult_name = Ognl.getValue("[1].name", context2, context2.getRoot());
		 
		 System.out.println("Ognl访问list中的嵌套元素: " + "[\n" 
				 + "size: " + result1 + "\n"
				 + "[0].id: " + firstResult_id +",[0].name: " + firstResult_name  + "\n"
				 + "[1].id: " + secondResult_id +",[1].name: " + secondResult_name  + "\n"
		 + "]");
	} catch (OgnlException e) {
		e.printStackTrace();
	} 
	
}

/**
 * Ognl访问java对象
 * 	源码片段:result = method.invoke(target, argsArray);
 * 	通过uesr(限定全名即org.yl.domain.User)找出所有方法名包括继承到的
 * 		user.getClass().getSuperclass()
 * 	然后遍历所有方法名,直到getName.endsWith(Name)为真找到method
 * 再然后找这个方法下的参数argsArray
 * 最后,result = method.invoke(target, argsArray);
 */
private static void testOgnlForObj() {
	User user = new User();  
    user.setName("刘可耕");

    try {
		Object nameResult = Ognl.getValue("name", user);
		
		System.out.println("Ognl访问对象属性user.name:" + nameResult);
		
		Company com = new Company();
		com.setCompanyName("志正股份责任公司");
		user.setComh(com);//setXXX中的XXX作为expression

		Object companlyNameResult = Ognl.getValue("comh.companyName", user);
		System.out.println("Ognl访问对象嵌套的属性user.company.companyName:" + companlyNameResult);
		
	} catch (OgnlException e) {  
        e.printStackTrace();
    }
	
}

/**
 * ognl访问Map
 * 	源码片段:
 * 		
        if (name.equals("size")) {
            result = new Integer(map.size());
        } else {
            if (name.equals("keys") || name.equals("keySet")) {
                result = map.keySet();
            } else {
                if (name.equals("values")) {
                    result = map.values();
                } else {
                    if (name.equals("isEmpty")) {
                        result = map.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
                    } else {
                        result = map.get(name);
                    }
                }
            }
        }
    
 */
private static void testOgnlForMap() {
	 Map rootMap=new HashMap(); 
        rootMap.put("money","10000");  
        rootMap.put("3月", "业绩");
        Object values;
        Object v;
		try {
			v = Ognl.getValue("money", rootMap);
			System.out.println("******Ognl访问Map中的元素: " + v);
			
			
			values = Ognl.getValue("values", rootMap);
			Collection c = (Collection)values;
			Iterator it = c.iterator();
			while(it.hasNext()){
				
				String vResult = (String)it.next();
				System.out.println("vResult:" + vResult);
			}
			System.out.println("******Ognl访问Map中的values: " + values);
			
			User user = new User();
			user.setName("郭德纲");
			rootMap.put("user", user);
			values = Ognl.getValue("user.name", rootMap);
			System.out.println("******Ognl访问Map中嵌套的元素: " + values);
			
		} catch (OgnlException e) {
			e.printStackTrace();
		} 
          
	
}

}

你可能感兴趣的:(java)