值栈(ValueStack)    

Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlContext),并将值栈设为OGNL的根对象。     
OGNL上下文中的根对象可以用ONGL表达式以对象名直接访问的,不需要使用任何特殊的“标记”,而引用上下文中的其他对象则需要使用“#”来标记。由于值栈是OGNL上下文中的根对象,因此可以直接访问。那么对于值栈中的对象该如何访问呢?Struts2提供了一个特殊的OGNLPropertyAccessor,它可以自动查找栈内的所有对象(从栈顶到栈底),直接找到一个具有你所查找的属性的对象。也就是说,对于值栈中的任何对象都可以直接访问,而不需要使用“#”。     
值栈中的对象都是OGNL上下文中的根对象。这就是Struts2在OGNL基础上做出的改进。 
 
ActionContext 
ActionContext是Action的环境,一次Action调用都会创建一个ActionContext 
调用:ActionContext context = ActionContext.getContext() 
 
Struts2对OGNL上下文的概念又做了进一步扩充,在struts2中,OGNL上下文通常如下所示: 
 
                        |--request  
 
                        |  
 
                        |--application  
 
                        |  
 
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]  
 
                        |  
 
                        |--session  
 
                        |  
 
                        |--attr  
 
                        |  
 
                        |--parameters  
 
在Struts2中,采用标准命名的上下文(Context)来处理OGNL表达式。处理OGNL的顶级对象是一个Map(也叫context map),而OGNL在这个context中就是一个顶级对象(root)。在用法上,顶级对象的属性访问,是不需要任何标记前缀的。而其它非顶级的对象访问,需要使用#标记。 
 
例如: 
Html代码  
<s:property value="%{#application.myApplicationKey}" />  
<s:property value="%{#session.mySessionKey}" />  
<s:property value="%{#request.myRequestKey}" />  
<s:property value="%{#parameters.myParameterKey}" />   
 
 
Struts2框架把OGNL Context设置为ActionContext。并且ValueStack作为OGNL的根对象。除value stack之外,Struts2框架还把代表application、session、request这些对象的Map对象也放到ActionContext中去。(这也就是Struts2建议在Action类中不要直接访问Servlet API的原因,他可以通过ActionContext对象来部分代替这些(Servlet API)功能。) 
 
 
 
Struts2把页面上的值传到Action里面,这个过程从逻辑上说需要分成两步来完成: 
 
1. 对于每个请求,都建立一个与相应Action对应的ActionContext作为OGNL的上下文环境和ValueStack,并且把Action里面的属性值压入ValueStack,这时的属性值都是初始化值。 
 
2. 在请求进入Action代码前,通过某种通用的机制(就是Struts2的interceptor拦截器机制),搜集页面上传递过来的参数,这里调用的是params拦截器,准确来说是这个拦截器会找Action里面的所有属性的set方法,把页面的Struts2标签的对应名称的属性值set进去,这样Action里面的属性就成功赋值。 
 
 
 
设计Struts2的团队初衷就是为了不用和那些Servlet API复杂的请求(Request)、响应(Response)关联在一起。 
 
 
 
 
Struts2的线程安全 
一般情况,我们的ActionContext都是通过:ActionContext context = (ActionContext) actionContext.get();来获取的。我们再来看看这里的actionContext对象的创建:static ThreadLocal actionContext = new ActionContextThreadLocal();,ActionContextThreadLocal是实现ThreadLocal的一个内部类。ThreadLocal可以命名为“线程局部变量”,它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。这样,我们ActionContext里的属性只会在对应的当前请求线程中可见,从而保证它是线程安全的。 
 
Struts2的action中就像一个POJO一样,定义了很多的类变量。此时,就使用scope=prototype来指定是个原型模式,而不是单例,这样就解决了线程安全问题。每个线程都是一个新的实例。