OGNL(Object-Graph Navigation Languaged)对象图导航语言,它是一种功能强大的第三方表达式语言。java中其他表达式语言还有EL,JSTL等。
目的:为了解struts2,弄懂ValueStack(据说struts2用的不多了,但一个mvc框架,学习一下还是可以的吧),因为struts2在项目中集成了OGNL,struts2默认的表达式语言就是OGNL。
OGNL的使用要素 就是 表达式 || 根对象 || Context对象
这里 就 先 探秘 OgnlContext类。
1)OgnlContext继承自Map接口(但是OgnlContext 内 _values 属性才是核心,也要注意_root这个属性。)
package ognl;
import ognl.enhance.LocalReference;
import java.util.*;
public class OgnlContext extends Object implements Map{}
与 _root 有关的一些代码如下
private Object _root;
private Object _currentObject;
public void setRoot(Object value)
{
_root = value;
_accessorStack.clear();
_typeStack.clear();
_currentObject = value;
if (_currentObject != null)
{
setCurrentType(_currentObject.getClass());
}
}
public Object getRoot(){ return _root; }
public void setCurrentType(Class type){ _typeStack.add(type); }
public void setCurrentObject(Object value){ _currentObject = value; }
public Object getCurrentObject(){ return _currentObject; }
与 _values 有关的一些代码如下
//定义 _values 属性
private Map _values = new HashMap(23);
//构造函数初始化 _values
public OgnlContext(Map values)
{
super();
this._values = values;
}
//设置 _values 的值
public void setValues(Map value)
{
for(Iterator it = value.keySet().iterator(); it.hasNext();) {
Object k = it.next();
_values.put(k, value.get(k));
}
}
//获取 _values 的值
public Map getValues() { return _values; }
实现Map接口的方法如下(全部和 _values 有关)
public int size(){ return _values.size(); }
public boolean isEmpty(){ return _values.isEmpty(); }
public boolean containsKey(Object key){ return _values.containsKey(key); }
public boolean containsValue(Object value){ return _values.containsValue(value); }
public void clear(){ ...; _values.clear(); setRoot(null); ...; }
public Set keySet(){ return _values.keySet(); }
public Collection values(){ return _values.values(); }
public Set entrySet(){ return _values.entrySet(); }
public boolean equals(Object o){ return _values.equals(o); }
public int hashCode(){ return _values.hashCode(); }
public Object get(Object key)
{
Object result;
//RESERVED_KEYS的11个保留的key,context,this,root等
//private static Map RESERVED_KEYS = new HashMap(11);
//RESERVED_KEYS.put(CONTEXT_CONTEXT_KEY, null);
//RESERVED_KEYS.put(ROOT_CONTEXT_KEY, null);
//RESERVED_KEYS.put(THIS_CONTEXT_KEY, null);
if (RESERVED_KEYS.containsKey(key)) {
//"this" 由setRoot方法可知,_currentObject 和 _root的值 一般相等
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
} else {
//"root"
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
} else {
//"context",返回当前OgnlContext对象
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
result = this;
}
//代码省略
} else {
除了上面的那些情况,就从_values中取值
result = _values.get(key);
}
return result;
}
public Object put(Object key, Object value)
{
Object result;
if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
setCurrentObject(value);
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
setRoot(value);
} else {
//context就是当前OgnlContext对象,不允许修改context的指向
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't change " + OgnlContext.CONTEXT_CONTEXT_KEY
+ " in context");
}
//代码省略
else {
//key不在预留的11个字符串中,那就把key-value对 put进 _value中
result = _values.put(key, value);
}
return result;
}
public Object remove(Object key)
{
Object result;
if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
setCurrentObject(null);
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
setRoot(null);
} else {
//context就是当前OgnlContext对象,不允许修改context的指向,当然就不允许为空
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
throw new IllegalArgumentException("can't remove " + OgnlContext.CONTEXT_CONTEXT_KEY
+ " from context");
}
//代码省略
else {
result = _values.remove(key);
}
return result;
}
public void putAll(Map t)
{
for(Iterator it = t.keySet().iterator(); it.hasNext();) {
Object k = it.next();
put(k, t.get(k));
}
}
看完之后,我们发现,其实 OgnlContext也就那样,它基本不依赖其他jar包,虽然实现了Map接口,但大多数数据(除了11个预定义的key,“this”,“root”,"context"等)都存在它的属性 _values 中。_values它就是一个HashMap。。。绕过来绕过去的感觉。。。有种避重就轻的感觉,那这个 OgnlContext 它 到底做了啥?
通过get方法,输入"context",可获得OgnlContext对象本身。
然后这个_root 作用未知。
数据呢,其实都存在了 HashMap中,也就是 _values 中。
OgnlContext 完整代码如下:
evaluations:评价,评估 trace: 跟踪,追溯 resolver: 解析 prefix: 前缀 reserved: 寡言收敛的,预留,保留,保守,储备
OgnlContext 类的代码可自行百度。



