Struts2中值栈ValueStack的使用

Struts2中值栈ValueStack的使用

1、什么是值栈?

值栈ValueStack是Struts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类。

当客户端发起一个请求时,Struts2架构会创建一个action实例对象,同时也会创建一个OgnlValueStack值栈实例对象,这个值栈对象将会贯穿整个Action的生命周期。

Struts2中使用OGNL将请求Action的参数封装为对象,存储到值栈中,可以通过OGNL表达式读取值栈中对象的属性值。


注意:

(1)ValueStack是接口,OgnlValueStack是实现类。

(2)值栈是Strust的一个容器,用于存取数据,基本不再使用域对象了。

(3)一次请求,创建一个Action实例对象和一个ValueStack对象。

(4)ValueStack对象的生命周期和对应的Action对象一样,请求响应后结束。


2、值栈的内部结构

(1)值栈(OgnlValueStack)的内部主要有两大区域:root 和 context。

CompoundRoot root;
transient Map<String, Object> context;

(2)root类型是Compound,这个类继承了ArrayList,是一个List集合。

public class CompoundRoot extends ArrayList { }

(3)context类型是Map<String, Object>,是一个HashMap集合。

(4)root中通常存放的是java对象。
context中放的是web开发常用的对象的引用(root, request, session, application, parameters, attr等)。也包括root的引用,所以说通过context也能获取root对象。

注意:
获取root中的数据,不需要加 # 号。
获取context中的数据,需要加 # 号。

我们所说的操作值栈,通常指的是操作ValueStack的root区域的数据。


3、ActionContext 和 ValueStack的关系

ActionContext:Action的上下文。

通过查看源码可以发现,当一个请求过来时,执行核心过滤器对象中的doFilter()方法,在这个方法中创建了ActionContext对象。

在创建ActionContext对象的过程中,会创建ValueStack对象,并将ValueStack对象传递给了ActionContext对象。所以我们可以通过ActionContext对象来获取到值栈ValueStack对象。

ActionContext对象之所以能够访问Servlet的API(访问的是域对象的数据,并不是域对象本身),是因为ActionContext内部有值栈的引用。


4、获取值栈对象

获取值栈对象有2种方法:
(1)通过ActionContext对象获取值栈。
(2)在Struts2的内部,将值栈也存入了request中。可以通过request对象获取值栈。

测试代码:

package com.pipi.struts2.valuestack;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.ServletActionContext;

import javax.servlet.http.HttpServletRequest;

// 获取ValueStack对象
public class ValueStackDemo1 extends ActionSupport {

    @Override
    public String execute() throws Exception {
        // 第一种:通过ActionContext对象获取
        ValueStack valueStack1 = ActionContext.getContext().getValueStack();

        // 第二种:通过request对象获取
        HttpServletRequest request = ServletActionContext.getRequest();
        ValueStack valueStack2 = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

        System.out.println(valueStack1 == valueStack2);  // true

        return NONE;
    }
}

一个Action实例中,只对应一个ValueStack对象。


5、向值栈中存入数据

存入数据有两种方式:
第一种:在Action中定义属性,并提供get方法。
第二种:使用ValueStack中本身的push(), set()方法(常用的)

(1)在Action中定义属性,并提供get方法。

默认情况下,Action对象本身都会压入到ValueStack中去,当然Action的属性也在里面。

先定义一个User类:
public class User {
    private String name;
    private Integer age;
    //.....
}

Action类:

package com.pipi.struts2.valuestack;

import com.opensymphony.xwork2.ActionSupport;

// 向值栈中存入数据
public class ValueStackDemo2 extends ActionSupport {

    // 方式一:定义属性,提供set和get方法
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String execute() throws Exception {
        user = new User("张三", 18);

        return SUCCESS;
    }
}

JSP页面:

<s:property value="user.name" />
<s:property value="user.age" />

当传递的数据过多时,定义属性显然会显得代码繁琐。


(2)第二种:使用ValueStack中本身的方法(常用的)

Action类:

package com.pipi.struts2.valuestack;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

// 向值栈中存入数据,使用ValueStack本身的方法
public class ValueStackDemo3 extends ActionSupport {

    @Override
    public String execute() throws Exception {

        // 先获得值栈对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();

        // 存入数据使用:push(Object);  set(String key, Object value);
        // 一般存入对象使用push(),存入集合使用set()
        User user = new User("张三", 20);

        // 手动压栈,user对象会在栈的顶部
        valueStack.push(user);

        return SUCCESS;
    }
}

JSP页面:

<s:property value="name" /><br />
<s:property value="age" /><br />

6、从值栈中获取数据

(1)获取值栈root区的一个对象的数据
(2)获取值栈root区的一个集合的数据(常用的)
(3)获取值栈context区,即引用域对象中的数据

Action类:

package com.pipi.struts2.valuestack;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.ServletActionContext;

import java.util.ArrayList;
import java.util.List;

// 向值栈ValueStack中存一个对象,存一个集合,在JSP页面取出
public class ValueStackDemo4 extends ActionSupport {

    @Override
    public String execute() throws Exception {
        // 获取值栈对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();

        // 向值栈中存一个对象
        valueStack.push(new User("张三", 33));

        // 向值栈中存一个集合
        List<User> list = new ArrayList<>();
        list.add(new User("李四", 44));
        list.add(new User("王五", 55));
        list.add(new User("赵六", 66));
        valueStack.set("userList", list);

        // 向值栈的context中存数据,即向域对象里存数据
        ServletActionContext.getRequest().setAttribute("userList1", list);
        ServletActionContext.getRequest().getSession().setAttribute("userList2", list);
        ServletActionContext.getServletContext().setAttribute("userList3", list);

        return SUCCESS;
    }
}

JSP页面:

	<h3>从值栈的root区取出一个对象的数据</h3>
    <s:property value="name" /><br />
    <s:property value="age" /><br />
    <hr />

    <h3>从值栈的root区取出一个集合的数据</h3>
    <s:property value="userList[0].name" /><br />
    <s:property value="userList[0].age" /><br />
    <s:property value="userList[1].name" /><br />
    <s:property value="userList[1].age" /><br />
    <s:property value="userList[2].name" /><br />
    <s:property value="userList[2].age" /><br />
    <hr />

    <h3>从值栈的context区取出域对象中的数据</h3>
    <s:property value="#request.userList1[0].name" /><br />
    <s:property value="#request.userList1[1].name" /><br />
    <s:property value="#request.userList1[2].name" /><br />
    <s:property value="#session.userList2[0].name" /><br />
    <s:property value="#session.userList2[1].name" /><br />
    <s:property value="#session.userList2[2].name" /><br />
    <s:property value="#attr.userList1[0].name" /><br />
    <hr />

运行截图:

在这里插入图片描述


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值