16. OGNL表达式
16.1 OGNL表达式语言简介
OGNL (Object Graph Navigation Language)对象图导航语言。Struts2框架使用OGNL作为默认的表达式语言。
OGNL相对其它表达式语言具有下面几大优势:
- 支持对象方法调用,如xxx.doSomeSpecial();
- 支持类静态方法的调用和值的访问,表达式的格式:
@[类全名(包括包路径)]@[方法名 | 值名],例如:
@java.lang.String@format(‘foo %s’, ‘bar’)
或@tutorial.MyConstant@APP_NAME; - 支持赋值操作和表达式串联;
- 访问OGNL上下文ActionContext;
操作集合对象List,Map。
Ognl 有一个上下文(Context)概念,在 Struts2 中上下文(Context)的实现为ActionContext,ActionContext对象对应Action,可以理解为action执行相关的对象的容器,包括application,session,parameters,locale,value stack等。ActionContext中:ValueStack是OGNL上下文的root元素,贯穿整个 Action 的生命周期(每个Action类的对象实例都拥有一个ValueStack 对象)。 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象。
private Map<String, Object> context;
这个才是真正意义上的上下文。其中可以put进数据,jsp中可通过OGNL表达式通过key获取。
OGNL Context 实现者为 ActionContext ,它结构示意图如下 :
注:这里的context map指的是ActionContext的map效果;action为相关的action包名,而不是action对象(代码中更清晰)。
16.2 理解Struts2中的 ValueStack和OGNL Context
ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。
ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象。
OgnlValueStack 类包含两个重要的属性:
CompoundRoot root; // CompoundRoot extends ArrayList
transient Map<String, Object> context;
- 其中root为一个ArrayList模拟的值栈,action等相关对象就是保存这里:
/**
* 实现ValueStack接口的pop操作
* @see com.opensymphony.xwork2.util.ValueStack#pop()
*/
public Object pop() {
return root.pop();
}
/**
* 实现ValueStack接口的push操作
* @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object)
*/
public void push(Object o) {
root.push(o);
}
再查看ActionContext类的源代码可知:
public class ActionContext implements Serializable {
static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();
// 所要执行的action类名
public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";
// 值栈ValueStack的类名,即上面所说的_root对象
public static final String VALUE_STACK = ValueStack.VALUE_STACK;
public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";
public static final String APPLICATION = "