Ongl 与 ValueStack ActionContext

转自:http://blog.sina.com.cn/s/blog_5c0522dd0100luqx.html

Ognl.setValue(String expr, Object obj, Object value) 与 Ognl.getValue(String expr, Object obj)执行规则:

上面两个函数都不支持以“#”开头的ognl表达式。

Ognl.getValue(“a.b.myFunction()”, obj)为例,执行规则如下:

1. 如果obj实现map接口:obj.get("a")
2. 如果obj不实现map接口:obj.getA()/isA()

返回的对象又根据上面的规则来执行get("b")或getB()/isB(),接着返回的对象执行myFunction()函数。

 

对应的,Ognl.setValue(“a.b.myFunction().d”, obj, value)的执行规则开始时与上面一样,到最后一步时:

1. 如果当前对象实现map接口则执行 put("d",value)
2. 如果当前对象不实现map接口则执行 setD(value)

正规的代码一个类不应该既有getA()方法又有isA()方法,所以我就没测试若这两个方法都有会执行哪个了。

 

Ognl.getValue(String expr, Map map, Object obj)执行规则:

如果expr以“#”开头,执行Ognl.getValue(expr.substring(1), map),否则执行Ognl.getValue(expr, obj)。

 

关于异常:
1.如果在执行函数之前没有获得对象,譬如说obj.getA()返回的是null,null再执行getB()/isB()就会产生空指针异常。
2.如果得到的对象没有下一个要执行的函数,譬如说obj.getA()返回一个对象,但这个对象没有getB()/isB()函数,也产生异常。
Ognl把上面两种异常都进行了封装,转抛出它定义的Ognl异常。

——————————————————————————————————————————————————

获得当前ActionContext:
ActionContext ctx = ActionContext.getContext();
ActionContext里面包含了一个Map结构,称为context。

 

获得ValueStack:
ValueStack stack = ActionContext.getContext().getValueStack();
ValueStack里面包含了一个List结构,称为root。

 

获得Root:
CompoundRoot root = ActionContext.getContext().getValueStack().getRoot();
CompoundRoot的数据结构是一个List,作为一个栈来使用。

 

获得Context:
Map<String,Object> context = ActionContext.getContext().getContextMap();
Map<String,Object> context = ActionContext.getContext().getValueStack().getContext();

——————————————————————————————————————————————————

根据ognl取出对象:
Object obj =  stack.findValue(String expr);
expr是指定对象的ongl表达式。找不到返回null,不抛异常。

根据ognl设置对象:
stack.setValue(String expr, Object value);
expr是被设置对象的ongl表达式。找不到等于什么都没干,不抛异常。
value是设置为该对象。

Root操作:
Object obj = stack.pop();   取出Root栈顶对象并把它从Root移除。
Object obj = stack.peek();  取出Root栈顶对象不把它从Root移除。
stack.push(Object o);       把对象o放入Root栈顶。

Context操作:
actionctx.put(String key, Object value); 把一个对象放入Context里。
key是放入Context时对象的key,value是放入Context的对象。

——————————————————————————————————————————————————
ValueStack的findValue(String expr)与setValue(String expr, Object value)的查找顺序:
如果ognl以#开始,只从context查找,否则从root的栈顶对象开始往下查找,找到后不会继续往下查找,如果root找遍后也没有,再到context里查找。

函数的执行规则与上面的Ognl.setValue/Ognl.getValue一样,根据当前对象的类型来判断执行get("a")/put("a",value)还是getA()/SetA(value)。

估计ValueStack的findValue()与setValue()函数就是上面Ognl的setValue,getValue等相关函数的封装。

——————————————————————————————————————————————————

struts2标签doTag()猜想
根据struts2标签的功能和上面说明,很容易猜想到struts2标签doTag()里面的结构,下面列出几个(只是我的猜想,没确认过源代码):

<s:property />   输出root栈顶对象
{
ValueStack stack = ActionContext.getContext().getValueStack();
Object obj = stack.peek();
通过pageContext获得response的输出流对象out;
out.print(obj);
}


<s:property value="name" />
{
ValueStack stack = ActionContext.getContext().getValueStack();
Object obj = stack.findValue("name");
通过pageContext获得response的输出流对象out;
out.print(obj);
}


<s:property value="#msg.time" />
{
ValueStack stack = ActionContext.getContext().getValueStack();
Object obj = stack.findValue("#msg.time");
通过pageContext获得response的输出流对象out;
out.print(obj);
}


<s:set name="firstEmp" value="empList[0]" />  往context放入对象:
{
ActionContext ctx = ActionContext.getContext();
ValueStack stack = ActionContext.getContext().getValueStack();
Object obj =  stack.findValue("empList[0]");
ctx.put("firstEmp", obj);
}


<s:push value="empList[0]">  往root栈顶放入对象
......
</s:push>  push标签结束就把对象从root栈顶取出恢复原状
{
ValueStack stack = ActionContext.getContext().getValueStack();
Object obj = stack.findValue("empList[0]");
stack.push(obj);
......
stack.pop();
}

 

你可能感兴趣的:(数据结构,Blog)