一.值栈是什么?
简单来说,值栈是对应每一个请求对象的轻量级的内存数据中心。
二.特点
1.它统一管理数据,供Action,Result,Interceptor等其他组件使用,这样一来,数据被集中管理,大大方便了编程。
2.大多数情况下,用户无需关心其内部,只需要去获取自己需要的数据就可以了,即用户可以隐式的使用值栈。
3.但当我们需要编写自定义的Result或拦截器等复杂功能时,还是需要显示访问值栈的,所以,我们应该掌握它。
三.值栈具体能干什么?
当有请求到达的时候,Struts2会为每个请求创建一个新的值栈,这个值栈中封装了一次请求的所有需要操作的相关数据。
正是因为值栈和请求的对应关系,因而值栈能保证线程安全地为每个请求提供公共的数据存储服务。
四.值栈的具体形式(两种)
一.狭义值栈
1.什么是狭义值栈?
通常指的是实现com.opensymphony.xwork2.util.ValueStack 接口的对象
此接口源码如下:
package com.opensymphony.xwork2.util;
import java.util.Map;
public interface ValueStack
{
public abstract Map getContext();
public abstract void setDefaultType(Class class1);
public abstract void setExprOverrides(Map map);
public abstract Map getExprOverrides();
public abstract CompoundRoot getRoot();
public abstract void setValue(String s, Object obj);
public abstract void setParameter(String s, Object obj);
public abstract void setValue(String s, Object obj, boolean flag);
public abstract String findString(String s);
public abstract String findString(String s, boolean flag);
public abstract Object findValue(String s);
public abstract Object findValue(String s, boolean flag);
public abstract Object findValue(String s, Class class1);
public abstract Object findValue(String s, Class class1, boolean flag);
public abstract Object peek();
public abstract Object pop();
public abstract void push(Object obj);
public abstract void set(String s, Object obj);
public abstract int size();
public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
public static final String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
}
目前就是com.opensymphony.xwork2.ognl.OgnlValueStack对象,它实现了上面接口。
由于源码过长,我们可以在类似于struts2-core-2.5.22.jar的文件中查找,也可以直接在java文件中继承它,用ctrl+左键查看。
2.狭义值栈的作用?
主要用来存取动态EL(表达式语言)运算需要的值和结果,OgnlValueStack对象主要是用来支持OGNL运算的(下一篇博客学习OGNL)。
3.狭义值栈中存放着一些OGNL可以存取访问的数据,典型如下:
Action实例。
OGNL表达式的值。
OGNL表达式产生的中间变量。
具体信息可查看源码。
二.广义值栈
通常指的是ActionContext对象,每个ActionContext是一个基本容器,包含着Action运行需要的数据。
源码如下:
package com.opensymphony.xwork2;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.ValueStack;
import java.io.Serializable;
import java.util.*;
import org.apache.struts2.dispatcher.HttpParameters;
// Referenced classes of package com.opensymphony.xwork2:
// ActionInvocation, XWorkException
public class ActionContext
implements Serializable
{
public ActionContext(Map context)
{
this.context = context;
}
public void setActionInvocation(ActionInvocation actionInvocation)
{
put("com.opensymphony.xwork2.ActionContext.actionInvocation", actionInvocation);
}
public ActionInvocation getActionInvocation()
{
return (ActionInvocation)get("com.opensymphony.xwork2.ActionContext.actionInvocation");
}
public void setApplication(Map application)
{
put("com.opensymphony.xwork2.ActionContext.application", application);
}
public Map getApplication()
{
return (Map)get("com.opensymphony.xwork2.ActionContext.application");
}
public static void setContext(ActionContext context)
{
actionContext.set(context);
}
public static ActionContext getContext()
{
return (ActionContext)actionContext.get();
}
public void setContextMap(Map contextMap)
{
getContext().context = contextMap;
}
public Map getContextMap()
{
return context;
}
public void setConversionErrors(Map conversionErrors)
{
put("com.opensymphony.xwork2.ActionContext.conversionErrors", conversionErrors);
}
public Map getConversionErrors()
{
Map errors = (Map)get("com.opensymphony.xwork2.ActionContext.conversionErrors");
if(errors == null)
{
errors = new HashMap();
setConversionErrors(errors);
}
return errors;
}
public void setLocale(Locale locale)
{
put("com.opensymphony.xwork2.ActionContext.locale", locale);
}
public Locale getLocale()
{
Locale locale = (Locale)get("com.opensymphony.xwork2.ActionContext.locale");
if(locale == null)
{
locale = Locale.getDefault();
setLocale(locale);
}
return locale;
}
public void setName(String name)
{
put("com.opensymphony.xwork2.ActionContext.name", name);
}
public String getName()
{
return (String)get("com.opensymphony.xwork2.ActionContext.name");
}
public void setParameters(HttpParameters parameters)
{
put("com.opensymphony.xwork2.ActionContext.parameters", parameters);
}
public HttpParameters getParameters()
{
return (HttpParameters)get("com.opensymphony.xwork2.ActionContext.parameters");
}
public void setSession(Map session)
{
put("com.opensymphony.xwork2.ActionContext.session", session);
}
public Map getSession()
{
return (Map)get("com.opensymphony.xwork2.ActionContext.session");
}
public void setValueStack(ValueStack stack)
{
put("com.opensymphony.xwork2.util.ValueStack.ValueStack", stack);
}
public ValueStack getValueStack()
{
return (ValueStack)get("com.opensymphony.xwork2.util.ValueStack.ValueStack");
}
public void setContainer(Container cont)
{
put("com.opensymphony.xwork2.ActionContext.container", cont);
}
public Container getContainer()
{
return (Container)get("com.opensymphony.xwork2.ActionContext.container");
}
public Object getInstance(Class type)
{
Container cont = getContainer();
if(cont != null)
return cont.getInstance(type);
else
throw new XWorkException("Cannot find an initialized container for this request.");
}
public Object get(String key)
{
return context.get(key);
}
public void put(String key, Object value)
{
context.put(key, value);
}
static ThreadLocal actionContext = new ThreadLocal();
public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";
public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";
public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application";
public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters";
public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";
public static final String TYPE_CONVERTER = "com.opensymphony.xwork2.ActionContext.typeConverter";
public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation";
public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors";
public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container";
private Map context;
}
我们从中可以看到它其实包含了ValueStack的。
五.ActionContext的基本使用
1.如何获取?
a.若不能获取到ActionInvocation的时候,可以使用ActionContext的一个静态getContext()方法获取:
ActionContext cts=ActionContext.getContext();
b.若能获取到的时候:
ActionContext cts=actionInvocation.getInvocationContext();
2.如何使用?
其典型方法如下:
get(String key) 根据key从ActionContext当前的存储空间里面获取值。
put(String key,Object value):把值存储在ActionContext存储空间里。
ValueStack getValueStack():获取OGNL栈值。
…具体多少方法大家可查看上面源码。
六.ValueStack的基本使用
1.如何获取
直接可由ActionContext对象的getValueStcak()方法获取。
2.典型方法如下:
Object findValue(String expr):根据表达式在value stack中,按照默认的访问顺序去获取表达式对应的值。
void setValue(String expr,Object value): 根据表达式按照默认的访问顺序设置值。
Object peek(): 获取value stack中的顶层对象,不修改value stack对象。
Object pop(): 弹出顶层对象。
void push(Object o): 压入对象。