先看这个表达式:list.{#me=#this,#root.map[#me]}
这个表达式有这么几个点:
1. #this
在"投影"里#this指向的是list的子元素, 我想这个大家都知道,就不多说了
2. #root
在"投影"里如何访问"投影"外面的元素,这个问题困扰了我很长时间, 今天看了下OGNL的源代码, 原来用#root可以访问根元素,#context可以访问上下文里的元素,#this可以访问当前对象的元素;
在struts里,原本最开始当前对象就是根元素,但到"投影"里就把当前对象指向了投影的子元素了
相关OGNL源代码如下:
if (RESERVED_KEYS.containsKey(key)) {
if (key.equals(OgnlContext.THIS_CONTEXT_KEY)) {
result = getCurrentObject();
} else {
if (key.equals(OgnlContext.ROOT_CONTEXT_KEY)) {
result = getRoot();
} else {
if (key.equals(OgnlContext.CONTEXT_CONTEXT_KEY)) {
result = this;
} else {
if (key.equals(OgnlContext.TRACE_EVALUATIONS_CONTEXT_KEY)) {
result = getTraceEvaluations() ? Boolean.TRUE : Boolean.FALSE;
} else {
if (key.equals(OgnlContext.LAST_EVALUATION_CONTEXT_KEY)) {
result = getLastEvaluation();
} else {
if (key.equals(OgnlContext.KEEP_LAST_EVALUATION_CONTEXT_KEY)) {
result = getKeepLastEvaluation() ? Boolean.TRUE : Boolean.FALSE;
} else {
if (key.equals(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY)) {
result = getClassResolver();
} else {
if (key.equals(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY)) {
result = getTypeConverter();
} else {
if (key.equals(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY)) {
result = getMemberAccess();
} else {
throw new IllegalArgumentException("unknown reserved key '" + key + "'");
}
}
}
}
}
}
}
}
}
} else {
result = values.get(key);
}
3. map[#me]
这样的写法和map.get(#me)的效果是一样, 但为什么不直接用#this呢? 原因在于4
4. #me=#this,
为什么这么写? (逗号表达式就不解释了)
因为“投影”里面的context与外面的context是不同的,但“投影”里的方法使用的确是外面的context(这算不算是一个BUG.....),所以只好用一个普通变量作为引用,防止因为上下文不一样,造成第2点中给出的源代码解析成错误的值.
总结,
OGNL使用起来,还是很方便的.官方对其使用方法的文档写的也非常详细,但像作用域这样的"隐藏"概念确没多少资料,希望我的这篇文章能给大家提供一点帮助.