Struts2--ValueStack

来源:互联网 发布:中国电信网络营业厅 编辑:程序博客网 时间:2024/05/16 19:18

一、什么是ValueStack
ValueStack是一个容器,它将action中产生的数据携带到页面上,实质上,ValueStack是Struts2对ognl的封装,它被设计成一个接口,com.opensymphony.xwork2.util.ValueStack,实现类为com.opensymphony.xwork2.ognl.OgnlValueStack。
ValueStack被保存在request中,所以每当客户端发送一个请求,服务器就会创建一个Action,对应着一个新的ValueStack。
二、ValueStack的内部结构
部分代码

    public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {    public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure";    private static final long serialVersionUID = 370737852934925530L;    private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";    private static final Logger LOG = LoggerFactory.getLogger(OgnlValueStack.class);    CompoundRoot root;    transient Map<String, Object> context;    Class defaultType;    Map<Object, Object> overrides;    transient OgnlUtil ognlUtil;    transient SecurityMemberAccess securityMemberAccess;    private transient XWorkConverter converter;    private boolean devMode;    private boolean logMissingProperties;

由root和context两部分组成。
CompoundRoot继承ArrayList,由pop()和push()增减数据。(栈结构)

public class CompoundRoot extends ArrayList {    public CompoundRoot() {    }    public CompoundRoot(List list) {        super(list);    }    public CompoundRoot cutStack(int index) {        return new CompoundRoot(subList(index, size()));    }    public Object peek() {        return get(0);    }    public Object pop() {        return remove(0);    }    public void push(Object o) {        add(0, o);    }}

content部位为一个HashMap。
在访问content map中的对象时要在前面加“#”,而访问root的对象时不需要加。在调用方法前,Action对象会被压入root中。

三、获取ValueStack

  1. 直接通过request对象获取、
ValueStack valueStack=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
  1. 使用ActionContext获取
    ActionContext context = ActionContext.getContext();    ValueStack stack = context.getValueStack();

四、ActionContext
ActionContext是action的上下文(容器),用于保存Action在执行过程中需要的一些对象,如Session,Parameters,ValueStack,Locale,同样是随着每次请求(每条线程)产生,所以线程安全。

public class ActionContext implements Serializable {    static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();

五、ValueStack存储数据

手动向ValueStack存储数据

stack.push("zz"); // 向root中存储stack.set("name", "zz"); //底层会创建一个HashMap,保存数据,在将hashMap存储到root中。

Struts2框架自动向ValueStack存储数据
上面也说过,在调用方法前,Action对象会被压入root中。在com.opensymphony.xwork2.DefaultActionInvocation的init方法中,有

if (pushAction) {            stack.push(action);            contextMap.put("action", action);        }

同时在com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor中,

public String intercept(ActionInvocation invocation) throws Exception {        Object action = invocation.getAction();        if (action instanceof ModelDriven) {            ModelDriven modelDriven = (ModelDriven) action;            ValueStack stack = invocation.getStack();            Object model = modelDriven.getModel();            if (model !=  null) {                stack.push(model);            }            if (refreshModelBeforeResult) {                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));            }        }        return invocation.invoke();    }

会将实现ModelDriven接口的对象压入ValueStack。

六、ValueStack获取数据
在页面通过struts2标签+ognl表达式获取数据

                <td><s:property value="name" /></td>                <td><s:property value="[0].top" /></td>

七、el表达式从ValueStack中获取值
由于Struts2用装饰者模式对request进行了增强,(org.apache.struts2.dispatcher.StrutsRequestWrapper),el表达式可以从ValueStack中得到值。

    ${model.username}

八、ognl表达式中的特殊字符

<body>    <%        request.setAttribute("name1", "xiaoming");        session.setAttribute("name2", "xiaohong");    %>    <h1>#号用法</h1>    <s:property value="#request.name1" />    <br>    <s:property value="#session.name2" />    <br>    <h2>%号用法</h2>    <s:property value="%{#request.name1}"/><br> <!-- 会解析成ognl -->    <s:property value="%{'#request.name1'}"/><br> <!-- 不会解析ognl -->    <s:debug /></body>

$号用法

        <action name="vsa" class="action.ValueStackAction">            <result name="success" type="redirect">/ognl.jsp?username=${model.username}</result>        </action>
0 0
原创粉丝点击