1.说明:结合ASTs演示Ognl取值机制,“此SAMPLE演示数据流转中的其中一环”
2.能力有限,有误差的请包含或指证
3.目的:抛砖引玉
4.内容:以下为主代码内容,javaBean(User和Company)就不贴出来了,看代码里的setter就可以构造出javaBean了
import java.util.HashMap;
import java.util.Map;
import ognl.Ognl;
import ognl.OgnlException;
/**
* 此SAMPLE主要演示表达式解析:Ognl.parseExpression(param)
* 用到了抽象语法树abstract systax trees (ASTs)
* JJTree interface for AST nodes:
* 1.ASTProperty-->PropertyAccessor
* 2.ASTVarRef
* 3.ASTChain
* 4.ASTEval
* 5.ASTStaticMethod
* 6.ASTStaticFiled
* 7.ExceptioinNode等
*
* AST Nodes作用:在节点之间提供一种构建父子关系的机制
*
* 思路:通过传递的参数param进行解析,构建相应的Node节点,
* 然后节点处理最终数值获取的业务逻辑(附流程图JJTree.jpg和Ognl取值流程图.jpg)
* @author 拈花为何不一笑
* @since 3/21/2018
*/
public class OgnlExpEngine2 {
/**
* 单元测试
* @param args
*/
public static void main(String[] args) {
// testForMapAndObject();
// testOgnlExpressCalc();
testOgnlMapping();
}
/**
* Ognl表达式与对象关系之间的映射
* 如:comh.companyName = "网络穷举大法科技有限公司"
* 应用场景:也许你会在View层的表单中使用user.username进行数据传递
* 而这种显示层的弱类型数据是如何与java对象(或对象之间的关系)进行
* 数据映射的。通过此方法就可以得到其背后机制
*
* 源码片段(把调用逻辑集中在for中为了演示说明,实际是分散开来的):
* 1.首先通过ASTs构建Node节点
* 2.其次,使用这些节点处理取值的逻辑,如下:
* SimpleNode: getValueBody(context, source)此抽象方法由子类实现
* for(int i = 0, ilast = _children.length - 1; i <= ilast; ++i){
* //(i)通过当前Node:ASTConst,找到字符串常量"comh"
* ASTProperty(comh):_children[i].getValue(context, result);
* //使用一个Node(ASTProperty)获取company实例,target=user,name="comh"
* ASTProperty:OgnlRuntime.getProperty(context, source, property)
* ObjectPropertyAccessor:getPossibleProperty(context, target, name)
*
* //(ii)再通过当前Node:ASTConst找到字符串常量"companyName":
* ASTProperty(companyName):_children[i].getValue(context, result);
* // 再使用一个Node(ASTProperty)获取companyName值,target=company,name="companyName"
* ASTProperty:OgnlRuntime.getProperty(context, source, property)
* ObjectPropertyAccessor:getPossibleProperty(context, target, name)
* }
*
*
*/
private static void testOgnlMapping() {
User user = new User();
user.setId(1001);
user.setName("刘思成");
Company company = new Company();
company.setCompanyName("网络穷举大法科技有限公司");
user.setComh(company);
Object mappingResult = null;
try {
mappingResult = Ognl.getValue("comh.companyName", user);
System.out.println("Ognl表达式与对象关系之间的映射comh.companyName:" + mappingResult );
} catch (OgnlException e) {
e.printStackTrace();
}
}
/**
* Ognl表达式计算
* 源码片段:通过Ognl.parseExpression(param)方法运用抽象语法树,
* 构建三个Node,node之间并且构建成父子关系的树型结构
*
* ASTAdd下面有二个子节点:ASTVarRef/ASTProperty
* (ASTAdd(父)-->ASTProperty(子); ASTAdd-->ASTVarRef-->ASTConst)
* 通过节点:ASTAdd,分别调用两个子节点,然后进行加法运算(有数字加法和非数字加法)
*
*/
private static void testOgnlExpressCalc() {
Map<String,Object> map = new HashMap<String,Object>();
map.put("describe", "风景好美");
User user = new User();
user.setId(168);
user.setName("妞妞");
Object calcResult = null;
try {
calcResult = Ognl.getValue(Ognl.parseExpression("#describe + name"), map, user);
//Ognl.getValue(Ognl.parseExpression("#describe + id + name"), map, user);
System.out.println("Ognl表达式计算: "+ calcResult);
} catch (OgnlException e) {
e.printStackTrace();
}
}
/**
* Ognl访问MAP和OBJECT
*
* 源码片段:ASTs(3000多行代码这里就略过了,思路注释OgnlExpEngine2类上)
*
*/
private static void testForMapAndObject() {
Map<String,Object> map = new HashMap<String,Object>();
map.put("describe", "风景好美");
User user = new User();
user.setId(168);
user.setName("妞妞");
try {
Object describe = Ognl.getValue(Ognl.parseExpression("describe"), map);
Object describe1 = Ognl.getValue(Ognl.parseExpression("#describe"), map,new Object());
System.out.println("Ognl访问map中的元素: " + describe1);
Object name = Ognl.getValue(Ognl.parseExpression("name"), user);
System.out.println("Ognl访问对象:" + name);
} catch (OgnlException e) {
e.printStackTrace();
}
}
}