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();
}
}
}