Struts2中值栈的概述

先推荐一篇不错的博客:值栈的概述

一、什么是值栈

ValueStack是Struts2框架的一个接口,翻译为值栈。OgnlValueStack是ValueStack的实现类,客户端发起一个请求,struts2框架会创建一个action实例的同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性。

二、值栈的内部结构

OnglValueStack的源码

public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
    CompoundRoot root;
    transient Map<String, Object> context;
}

CompoundRoot的源码

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);
    }
}

由上面的源码可以看出,OgnlValueStack中包扩两部分,值栈Map(即ognl的上下文)。

Context:即OgnlContext上下文,它是一个Map结构,上下文中存储了一些引用,parameters、request、session、application等,上下文的Root为CompoundRoot。

CompoundRoot:存储了action实例,它作为OgnlContext的Root对象。CompoundRoot继承ArrayList实现压栈和出栈功能,拥有栈的特点:先进后出,后进先出,最后压进栈的数据在栈顶。我们把它称为对象栈。

Struts2对原OGNL(OGNL表达式的详解)作出的改进就是Root使用了CompoundRoot(自定义栈),使用OgnlValueStack的findValue()方法可以在CompoundRoot中从栈顶向栈底查找对象的属性值。

CompoundRoot作为OgnlContext的Root对象,并且在CompoundRoot中的action实例位于栈顶,当读取action的属性值时会先从栈顶对象中找对应的属性,如果找不到则继续找栈中的其他对象,如果找到则停止查找。

三、ActionContext和ValueStack的关系

在创建ActionContext的时候,同时创建ValueStack的对象,将ValueStack对象给ActionContext。

ActionContext中有一个ValueStack的引用,同时ValueStack中也有一个ActionContext的引用。

四、获取值栈对象

1、通过ActionContext对象获取值栈

ValueStack stack = ActionContext.getContext().getValueStack();

2、通过request域获取值栈

ValueStack stack = (ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

五、操作值栈

1、对Action中的属性提供get方法的方式

因为Action本身就在值栈中,Action中的属性也就默认在值栈中了,所以我们可以通过对Action的属性提供的get方法的方式来操作值栈。

2、手动操作值栈

调用值栈的push和set方法对值栈进行操作。

OgnlValueStack中push和set的区别:


public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
    CompoundRoot root;
    public void push(Object o) {
        root.push(o);
    }
 
    public void set(String key, Object o) {
        //set basically is backed by a Map pushed on the stack with a key being put on the map and the Object being the value
        Map setMap = retrieveSetMap();
        setMap.put(key, o);
    }
 
    private Map retrieveSetMap() {
        Map setMap;
        Object topObj = peek();
        if (shouldUseOldMap(topObj)) {
            setMap = (Map) topObj;
        } else {
            setMap = new HashMap();
            setMap.put(MAP_IDENTIFIER_KEY, "");
            push(setMap);
        }
        return setMap;
    }
 
    public Object peek() {
        return root.peek();
    }
 
    private boolean shouldUseOldMap(Object topObj) {
        return topObj instanceof Map && ((Map) topObj).get(MAP_IDENTIFIER_KEY) != null;
    }
}

通过源码可以看出,push直接将对象压入CompoundRoot中,set如果第一次使用,会创建一个map对象,并将键值对设置进去,如果不是第一次,则会将键值对直接放入该map中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值