Struts2的值栈理解---ValueStack

一.什么是值栈


1.ValueStack是Struts2中提供的一个接口,只有一个实现类OgnlValueStack,我们平时使用的OGNL表达式就是从值栈中获取值.

2.我们编写的每一个Action都有与之对应的值栈对象,也就是说每一次Action请求都会产生一个ValueStack对象

3.Struts2框架把ValueStack保存在名称为struts.valueStack的request属性中


二.值栈的内部结构


1.值栈由两部分组成:root+contextMap:

root():是一个List结构,Struts2会把Action和一些对象压入Root中

contextMap:是一个map集合,保存的是一些映射,其中request,session,application的值都会保存到contextMap这个大Map中

2.contextMap的组成:Struts 会把下面这些映射压入 ContextMap 中

parameters: 该 Map 中包含当前请求的请求参数  ?name=xxx&password=123
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application  对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application

3.ValueStack 和 ActionContext 是什么关系 ?
                
            
class A{
                B b;
            }
            class B{
                A a;
            }
        
        ValueStack 和 ActionContext,是互相引用.值栈对象是请求时创建的:
        doFilter中 prepare.createActionContext(request, response); 
        创建ActionContext 对象过程中,创建 值栈对象ValueStack 
        ActionContext对象 对 ValueStack对象中的context是 有引用的 (在程序中 通过 ActionContext 获得 值栈对象 ) 
        ActionContext.getContext();返回的ActionContext对象。(还有值栈的引用)
        Dispatcher类 serviceAction 方法中 将值栈对象保存到 request范围
        request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());


在Struts2的创建ActionContext在核心控制器执行时创建:



4.获得值栈对象 有两种方法

ValueStack valueStack = (ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
5.向值栈保存数据 (默认是向 root中保存数据)
        alueStack.push(Object obj);push方法的底层调用root对象的push方法(把元素添加到0位置)

ValueStack源码片段:

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object)
     */
    public void push(Object o) {
      root.push(o);
    }
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);
    }
}

        valueStack.set(String key, Object obj);源码获取map集合(map有可能是已经存在的,有可能是新创建的),把map集合push到栈中,再把数据存入到map集合中。

ValueStack中set方法原理:

    /** 
     * @see com.opensymphony.xwork2.util.ValueStack#set(java.lang.String, java.lang.Object)
     */
    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;
    }


        在jsp中 通过 <s:debug /> 查看值栈的内容 
6.值栈理解图解:

          
7.获取值栈中的数据:

一般情况向我们是将对象利用root的push的方式压入栈顶,这时候获取值的时候,直接根据对象的属性获取即可:

后台代码:

ValueStack stack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
User user = new User();
stack.push(user);
前台获取:username和age为user的属性
<s:property value="username"/>
<s:property value="age"/>
如果压入的数据是集合形式,我们一般使用set的方式将数据压入栈顶,然后在前台进行获取,根据键的名称获取:

后台代码:

ValueStack stack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
stack.set("name","张三");
前台获取:
<s:property value="name"/>

8.EL表达式为什么可以从值栈中取值:

EL表达式可以从值栈中取值的原因在于,Struts2对request进行了增强,而EL表达式取值的本质就是调用request的getAttribute.Struts2中的request.getAttribute首先会进行普通的获取值,如果没有拿到则会去值栈中从上往下扫描,所以EL表达式会获取到值栈中的数据.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值