应用:ValueStack

理解ValueStack的基本机制!对各种现象作出解释。

ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!

ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致),同时ValueStack暴露相关的接口:

void setValue(String expr, Object value);

Object findValue(String expr);

用来通过OGNL表达式对ValueStack中的数据进行操作!

值栈就是一个List.

ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!


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

}

}

正是通过这两个方法,CompoundRoot变成了一个栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!

OGNL不支持多个root对象,而struts2能够支持多个root对象,它对OGNL做了扩展。

如果某个OGNL表达式被传递给ValueStack(即调用ValueStack的setValue或findValue方法),而表达式中包含有对root对象的访问操作,ValueStack将依次从栈顶往栈底搜索CompoundRoot对象中所包含的对象,看哪个对象具有相应的属性,找到之后,立刻返回。

在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素。看下面的代码:


public class UserAction {

private String username;

private Integer age;

private boolean valid;

//查看用户的详细信息

public String detail(){

username = "张三";

age = 18;

valid = true;

return "detail";

}

在Action中,给Action的username/age/valid赋值。Detail页面如下:


username:<s:property value="username"/> <br/>

valid:<s:property value="valid"/> <br/>

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

上述JSP页面将能正确将它们的值取出。<s:property value=”ognl表达式”/>。在s:property标签中的OGNL表达式,最终会交给ValueStack来解释。username就是一个OGNL表达式,意思是调用root对象的getUsername()方法。Struts2将自动搜索CompoundRoot中有哪些元素(从第0个元素开始搜索),检测这些元素是否有getUsername()方法,如果第0个元素没有getUsername()方法,将继续搜索第1、2、3……个元素是否有getUsername()方法。

在上面的例子中,CompoundRoot中只有一个对象,就是userAction对象,而这个对象中正好有getUsername()方法,所以,上述JSP代码将能够将值正确取出。

再看下面的例子:


public class UserAction {

private String username;

private String name;

//查看用户的详细信息

public String detail(){

username = "张三";

name = "王五";

User u = new User();

u.setUsername("赵毅");

ActionContext.getContext().getValueStack().push(u);

return "detail";

}

在上面这个UserAction的代码中,我们直接调用ActionContext.getContext().getValueStack().push()方法,把一个User对象(这个对象拥有getUsername()和setUsername()方法)直接压入到ValueStack中,这时候,在ValueStack的CompoundRoot中将有两个元素:第0个元素是刚刚压入的user对象[赵毅],而第1个元素是userAction对象[张三],如果在JSP中使用下面的表达式来取值:

<s:property value=”username”/> ,那么输出的值将是“赵毅”!道理上面已经讲过了,struts2将会从第0个元素开始搜索CompoundRoot中的对象,第0个元素正是刚刚压入的那个user对象!

如果在JSP中使用<s:property value=”name”/>来取值,将取出“王五”,因为第0个元素user对象没有name属性,所以,会继续搜索第1个元素userAction对象,在这个对象中就有name属性了!

再看下面的代码:


public class UserAction {

private String username;

//查看用户的详细信息

public String detail(){

username = "张三";

List list = new ArrayList();

for(int i=0; i<10; i++){

User user = new User();

user.setUsername("User"+i);

list.add(user);

}

ActionContext.getContext().put("users", list);

User u = new User();

u.setUsername("赵毅");

ActionContext.getContext().getValueStack().push(u);

return "detail";

}

对应的JSP如下:


1:  <s:property value="username"/> <br/>

2:  <s:iterator value="#users">

3:     <s:property value="username"/>

4:     <s:property value="#root[2].username"/><br/>

5:  </s:iterator>

6:  <s:property value="username"/>

7:  <s:property value="#root[1].username"/> <!-- 张三 -->

根据刚才的示例,我们知道,第1行的username是“赵毅”(因为JSP在执行这行代码的时候,CompoundRoot中有两个元素:第0个是“user对象赵毅”,第1个是“userAction对象张三”),因此第1行的username将取出CompoundRoot中第0个元素的username属性:赵毅

第2行代码是iterator标签,只定义了一个value属性,iterator标签将循环访问users这个List中的User对象,并把当前循环的user对象压入到CompoundRoot中!所以,在第3行和第4行代码被执行的时候,CompoundRoot中总共有3个元素:第0个元素是被iterator标签压入的当前循环的user对象;第1个元素是“user对象赵毅”;第2个元素是“userAction对象张三”,因此第3行代码的执行结果就是输出“UserX”,即当前循环的user对象的username属性!iterator标签将会依次取出List中的user对象,并不断压入/弹出user对象(每次循环,都将执行一遍压入/弹出)。而第4行代码取第2个元素的username属性,即userAction对象的username属性:张三。

第5行代码执行完成之后,在CompoundRoot中将剩下2个元素,与第2行代码被执行之前一样。所以,第6行代码的输出和第1行代码的输出结果是一样的,而第7行代码将取出userAction对象的username属性:张三

时间: 2024-08-29 00:26:10

应用:ValueStack的相关文章

【Struts2】剖析Struts2中的反射技术 ValueStack(值栈)

1,Struts2框架主要组件的处理流程 在说ValueStack之前,笔者先说一说Struts2中常用的组件,struts2中常用组件有strutsPrepareAndExecuteExceptionn,以及一般执行流程: 请求来进入 Filter 控制器 Filter 控制器创建 ValueStack 对象并初始化 Filter 控制器根据 struts.xml 调用 defaultStack 拦截器栈 Filter 控制器根据 struts.xml 调用 Action 处理 Filter

关于在jsp页面中使用/struts-tags标签库的迭代器时,从ValueStack获取参数使用EL的问题

情况复原下: 通过valuestack存了个user,然后页面里可以${user.sex}拿到男.${user.sex=='男'}拿到ture 但是在使用 <s:if text="${user.sex=='男'}">报错   <c:if text="${user.sex=='男'}">可以用 分析: 我们都知道Struts2是对request进行增强了的,在getAttribute()无法获取数据时,会从ValueStack中获取. 那么用s

Ognl表达式 值栈对象ValueStack

ValueStack值栈主要包含另个部分: 1.map栈(非根元素) context:主要存储域对象. 2.list栈(根元素) root:主要存储 (1)通过值栈的push()方法存放的对象 (2)Map对象(通过值栈的set()方法存放的数据) (3)Action对象 (4)其他代理对象. 测试类OgnlDemo2 <span style="font-size:14px;"><span style="font-family:Courier New;&qu

Struts2之ValueStack笔记

1.web基础知识——redirect和dispatch的区别 “redirect”方式中,服务器做的工作是处理浏览器请求然后告诉浏览器你访问的资源在另一位置(url),然后浏览器再次发起请求访问指定的资源: “dispatch”方式中,服务器会把浏览器的请求看做一种资源(request),这份资源会在服务器中流通,不同处理程序都能对其加工处理: respone在这两种不同方式中也有这种区别: 在struts2中,我认为理解redirect和dispatch的区别很重要. 2.没有读struts

ValueStack与ContentMap (ActionContext.getContext().getValueStack().set())

在方法 <action name="zilei" class="dtreeAction" method="zilei">   <result name="listzilei" >/zilei.jsp</result>   <result name="input">/error.jsp</result>  </action> Action

什么是ValueStack

转载自:http://www.cnblogs.com/zyw-205520/archive/2012/09/12/2681346.html Strut2的Action类通过属性可以获得所有相关的值,如请求参数属性值等.要获得这些参数值,我们要做的唯一一件事就是在Action类中声明与参数同名的属性.在Struts2调用Action类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值.要完成这个功能,有很大程度上,Struts2要依赖于ValueStack对象.这

ValueStack值栈和ActionContext

Struts2在OGNL之上提供的最大附加特性就是支持值栈(ValueStack),在OGNL上下文中只能有一个根对象,Struts2的值栈则允许存在许多虚拟对象. 一:值栈(ValueStack) 我们可以先获得ValueStack接口对象 // 01.获取到ValueStack接口对象 ,在request请求中. HttpServletRequest request = ServletActionContext.getRequest(); ValueStack vs = (ValueStac

OGNL valueStack StackContext(ActionContext)深入分析(转+个人理解)

//还会补充 首先要有一个意识 ,为什么要了解这个?: struts2中的表单是怎么通过表达式(EL or OGNL)来传给Action 和 拿到Action的值的. 值栈(根)对象也可以直接使用EL表达式访问,比如这里可以直接通过${user.username}来获取username的值,我们知道el表达式只能访问四种scope范围内的对象,那为什么这里能访问到值栈对象呢?原因是struts2对HttpServletRequet进行了一次封装,封装的代码主要是重写了getAttribute方法

Struts2中的ValueStack理解

1.目标 重新认识下ValueStack: 2.图解 3.解释下用法 struts2中在页面取值的话:是这样的,root中可以直接取值不用加# 但是在ActionContext中取值则需要加#访问才能取到值: 4.struts2中debug标签所对应的root和ActionContext;

[转]Struts2数据传输的背后机制:ValueStack(值栈)

1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! 2. ValueStack基础:OGNL 要了解ValueStack,必须先理解OGNL(Object Graphic Navigatino Language)! OGNL是Struts2中使用的一种表达式语言,它可以: ①用于JSP的标签库中,以便能够方便的访问各种对象的属性: ②用于界面将参数传递到Action(并进行类型转换)中: ③用于struts2的配置文件中! 所以,非常有