Struts_ValueStack,Ognl

1.OgnlContext类【本质是一个Map】

public class OgnlContext extends Object implements Map

方法:

Object
put(String key, Object value)//往非根栈中设置值

void
setRoot(Object value)//往根栈(root栈中)设置值

Object
getRoot()//得到根栈

2.Ognl类

public abstract class Ognl extends Object

This class provides static methods for parsing and interpreting OGNL expressions.

查看文档发现,此方法所有的方法都是抽象的,所以不用实例化此方法,直接用类名调用

static Object
parseExpression(String expression)
          Parses the given OGNL expression and returns a tree representation of the expression that can be   used by Ognl static methods

static <T> T
getValue(Object tree, Map<String,Object> context, Object root)
          Evaluates the given OGNL expression tree to extract a value from the given root object.

public class OgnlDemo1 {
    @Test
    public void test1() throws OgnlException {
        // 创建一个OgnlContext对象
        OgnlContext ognlContext = new OgnlContext();
        User user = new User();
        user.setAge("20");
        user.setName("小王");
        // 往非根元素放入值,取值要用#
ognlContext.put("user", user);// 键值对
        User user1 = new User();
        user1.setAge("30");
        user1.setName("小李");
        // 往根元素放入值
ognlContext.setRoot(user1);// 直接把对象放入,不是键值对
        // 获取非根数据
        // 先构建一个tree
   Object tree = Ognl.parseExpression("#user.age”);

Object value = Ognl.getValue(tree, ognlContext, ognlContext.getRoot());
        System.out.println(value);
        // 获取根元素数据
        // 先构建一个tree
    Object tree1 = Ognl.parseExpression("age");// <s:property
                                                        // value="#user.age"/>
        Object value1 = Ognl.getValue(tree1, ognlContext, ognlContext.getRoot());
        System.out.println(value1);
    }

}

3.ValueStack接口:

默认实现类:OgnlValueStack

1.获取值栈对象的三种方式:

(1)ValueStack valueStack = ActionContext.getContext().getValueStack();
                ActionContext为Action的上下文,其中有重要的6大对象
                  * valueStack,parameters,request,session,application,attr
(2)ValueStack valueStack = ServletActionContext.getValueStack(ServletActionContext.getRequest());      
                ServletActionContext继承了ActionContext,它与web容器耦合,可以获取web容器的一些信息.

(3)ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

public class Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        //每次访问创建一个Action对象和ValueStack对象,把Action对象放入到
        //ValueStack对象中,把ValueStack对象放入到Request对象域中
        HttpServletRequest request = ServletActionContext.getRequest();
        ValueStack vs1=(ValueStack) request.getAttribute("struts.valueStack");
        ActionContext ac = ActionContext.getContext();
        ValueStack vs2 = ac.getValueStack();
        ValueStack vs3 = ServletActionContext.getValueStack(ServletActionContext.getRequest());

System.out.println(vs1==vs2);//true
        System.out.println(vs1==vs3);//true
        return SUCCESS;
    }

}

2.ValueStack对象内部

ValueStack对象:

root栈(CompoundRoot):即list栈,存放Action对象及全局属性

context栈(OgnlContext):即map栈存放映射的数据

//root栈中维护了Action对象即其全局变量

public class Action extends ActionSupport{
    @Override
    public String execute() throws Exception {
        ActionContext ac = ActionContext.getContext();
        ValueStack vs = ac.getValueStack();

//打断点
        System.out.println(vs);
        return SUCCESS;
    }

}

//Action对象就放入ValueStack对象的root栈中

CompoundRoot extends ArrayList

//ActionContext中有这三个对象:request、session、application

public class Action extends ActionSupport{

//Action中全局的成员,都放入ValueStack对象中root栈中的Action对象中,即都是放入根元素中,取值不加#
    private User user1=new User(1306,"小王");
    @Override
    public String execute() throws Exception {
        //得到ActionContext对象
        ActionContext ac = ActionContext.getContext();

//下面三个存放在非根元素OgnlContext中,取值要加#
        ac.getContextMap().put("request_data", "request_data");
        ac.getSession().put("session_data", "session_data");
        ac.getApplication().put("application_data", "application_data");
        ValueStack vs = ac.getValueStack();
        System.out.println(vs);

//打断点
        return SUCCESS;
    }

}

3.ValueStack对象方法:

都是操作root根栈中元素

getRoot():得到root对象

push();往root栈顶放元素

pop();从root栈栈顶移除元素

set("user1", new User(110,"警察"));往root栈栈顶放入map元素

public class Action extends ActionSupport{
    //ValueStack对象存储Action对象,即值栈对象存储所有数据
    private User user1=new User(1306,"小王");
    @Override
    public String execute() throws Exception {
        //得到ActionContext对象
        ActionContext ac = ActionContext.getContext();
        ac.getContextMap().put("request_data", "request_data");
        ac.getSession().put("session_data", "session_data");
        ac.getApplication().put("application_data", "application_data");
        ValueStack vs = ac.getValueStack();
  vs.getRoot().push(new User(110,"警察"));//放入栈顶
        //vs.push(new User(110,"警察"));与上面效果等价

System.out.println(vs);
        return SUCCESS;
    }

}

分析:

vs.getRoot().push(new User(110,"警察"));ValueStack用getRoot()方法直接得到root对象,root对象是ArrayList,push方法把new User(110,"警察"));放入root中

注意两个user对象的不同!一个是在root下,一个是在root下的Action对象下

ValueStack中root栈栈顶元素的变化

public class Action extends ActionSupport{
    //ValueStack对象存储Action对象,即值栈对象存储所有数据
    private User user1=new User(1306,"小王");
    @Override
    public String execute() throws Exception {
        //得到ActionContext对象
        ActionContext ac = ActionContext.getContext();
        ac.getContextMap().put("request_data", "request_data");
        ac.getSession().put("session_data", "session_data");
        ac.getApplication().put("application_data", "application_data");
        ValueStack vs = ac.getValueStack();

//断点
        vs.getRoot().push(new User(110,"警察"));//放入栈顶
        //vs.push(new User(110,"警察"));与上面效果等价
        vs.pop();//移除栈顶元素
        System.out.println(vs);
        return SUCCESS;
    }

}

vs.getRoot().push(new User(110,"警察"));//放入栈顶

vs.pop();//移除栈顶元素

//也是往root栈存储,map结构 在jsp页面中取值  user1.userId  user1.userName

public class Action extends ActionSupport{
    //ValueStack对象存储Action对象,即值栈对象存储所有数据
    private User user0=new User(1306,"小王");
    @Override
    public String execute() throws Exception {
        //得到ActionContext对象
        ActionContext ac = ActionContext.getContext();
        ValueStack vs = ac.getValueStack();
        //也是往root栈存储,map结构 在jsp页面中取值  user1.userId  user1.userName
        vs.set("user1", new User(110,"警察"));
        vs.set("user2", new User(119,"火警"));
        System.out.println(vs);
        return SUCCESS;
    }

}

4.注意

1.在action中只有给全局变量get set方法才能在jsp页面中用OGNL表达式取出

5.仔细思考下面的代码【参看第6点】

ActionContext ac=ActionContext.getContext();

ac.getContextMap();—>脑中想出debug的图 取值可以省略request     #key

ac.get(“requset”);—>想出debug的图 取值不可以省略request     #request.key

request session application attr parameters对象

ActionContext ac=ActionContext.getContext();

1)ac.getContextMap()方法得到的request

如果往request域中存数据,
数据直接为  key value形式存放在ognlContext中,若有多个数据放入,则在ognlContext对象中为多组key value

所以取值可以直接  #key  不用加request

2)(Map<String, Object>) ac.get("request")  推荐这种方法获得真正的request的map

得到的request,是一个request的map

需要 #request.key

除了ac.getContextMap(),别的都是向下面一样 key value,value又是一个map<key,value>

3)ServletActionContext.getRequest().setAttribute("username","joey");同2)
除了request,session application attr parameters都是key value,value又是一个map<key,value>

而且如果同过两种不同的方法得到request,那么可以分别往其内放入完全相同的key map值

6.常用的存储数据的方法

(1)向map栈中存数据,即ValueStack中的context(OgnlContext)
* 通过request,session等向map中存储数据
ServletActionContext.getRequest().setAttribute("username","joey");
                ServletActionContext.getSession().put("pwd","123");
  * 直接向map栈中放数据【在之前被认为是得到request对象,然后往request对象中放!!】
                ActionContext.getContext().put("msg","how you doing");
(2)向对象栈中存数据,即ValueStack中的root(CompoundRoot)对象
            * 先得到root,再把数据压入到root中,这种方式是放入到栈底.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(new Person());
            * 先得到root,利用add(index,Object)把一个对象压入到root中指定位置.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(0,new Person());//这里0,表示压入栈顶.
            * 存放一个map到对象栈中
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.set("msg","dude"); //先封装成Map,在把Map放入到对象栈中,且放入栈顶.
            * 利用valueStack的push方法把一个对象直接压入栈顶
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.push(new Person());

下面内容原文地址:http://blog.csdn.net/wyply115/article/details/8257140

一、ValueStack
1.ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用
实现了ValueStack接口的类OgnlValueStack.它是ValueStack的默认实现类.
2.ValueStack贯穿整个action的生命周期,每一个action实例都拥有一个ValueStack对象,其中保存了当前action对象和其他相关对象.

3.struts2把ValueStack对象保存在名为:struts.valueStack的request域中.即ValueStack作用域为request.当action创建的时候,ValueStack就创建了,action被销毁的时候,ValueStack就销毁了

struts.valueStack放入request域中

4.ValueStack中的数据分两部分存放:root(栈结构,CompoundRoot)和context(map形式,OgnlContext)
(1)    * 其中的root对象是CompoundRoot,CompoundRoot继承了ArrayList,提供了额外的方法:push(),和pop()方法,
用来对root对象中所包含的数据进行存取.正是由于这两个方法,CompoundRoot变成了一个栈结构.
            * struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack
的CompoundRoot中),所以action对象是CompoundRoot中的一个元素.
(2)* 其中的context对象是OgnlContext,它实现了map接口,在valuestack的默认实现类中,即OgnlValueStack类中,
调用ongl中的方法:Ognl.createDefaultContext(..)给context赋值,查看源代码可知,
此方法返回的是一个OgnlContext对象.
5.获取ValueStack的三种方式
(1)ValueStack valueStack = ActionContext.getContext().getValueStack();
                ActionContext为Action的上下文,其中有重要的6大对象
                    * valueStack,parameters,request,session,application,attr
                    * 而ognl表达式必须选择AcitonContext中的一个对象作为根对象(root),默认为valueStack,因此访问valueStack中的数据不加#
而如果要使用另外5个对象作为根对象,需要加#前缀.
(2)ValueStack valueStack = ServletActionContext.getValueStack(ServletActionContext.getRequest());      
                ServletActionContext继承了ActionContext,它与web容器耦合,可以获取web容器的一些信息.

(3)ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

6.ValueStack内存结构图

7.常用的存储数据的方法
(1)向map栈中存数据,即ValueStack中的context(OgnlContext)
            * 通过request,session等向map中存储数据
          ServletActionContext.getRequest().setAttribute("username","joey");
                ServletActionContext.getSession().put("pwd","123");
   * 直接向map栈中放数据
                ActionContext.getContext().put("msg","how you doing");
(2)向对象栈中存数据,即ValueStack中的root(CompoundRoot)对象
            * 先得到root,再把数据压入到root中,这中方式是放入到栈底.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(new Person());
            * 先得到root,利用add(index,Object)把一个对象压入到root中指定位置.
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.getRoot().add(0,new Person());//这里0,表示压入栈顶.
            * 存放一个map到对象栈中
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.set("msg","dude"); //先封装成Map,在把Map放入到对象栈中,且放入栈顶.
            * 利用valueStack的push方法把一个对象直接压入栈顶
                ValueStack valueStack = ActionContext.getContext().getValueStack();
                valueStack.push(new Person());

8.利用OGNL表达式取ValueStack中的数据
(1)<s:property />:取栈顶的元素.
(2)<s:iterator />:取栈顶的元素.
注意:此标签的value属性值无论来自对象栈还是Map栈,都可以不加#前缀(<s:select/>标签也适用).
因为此标签在迭代的时候,总是把当前正在迭代的元素放入到栈顶.

二、ognl
    1.ognl是struts2中使用的一种表达式语言,可用于jsp的标签库中,以方便访问各种对象的属性.
它用于把界面的参数传递到Action中(并进行类型转换),它还可以用于struts2的配置文件中.
  2.Root对象
        OGNL称为对象图导航语言,所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其它对象.
例如:

[java] view plaincopyprint?

1. public class User{

2. private String username;

3. private Group group;

4. //省略setter,getter方法

5. }

6. public class Group{

7. private String name;

8. private Organization org;

9. //省略setter,getter方法

10. }

11. public class Organization{

12. private String orgId;

13. //省略setter,getter方法

14. }

[java] view plaincopyprint?

1. public class User{

2. private String username;

3. private Group group;

4. //省略setter,getter方法

5. }

6. public class Group{

7. private String name;

8. private Organization org;

9. //省略setter,getter方法

10. }

11. public class Organization{

12. private String orgId;

13. //省略setter,getter方法

14. }

public class User{

private String username;

private Group group;

//省略setter,getter方法

}

public class Group{

private String name;

private Organization org;

//省略setter,getter方法

}

public class Organization{

private String orgId;

//省略setter,getter方法

}

以上三个类,描述了通过一个User对象,同过User对象可以导航到Group对象,进而导航到Organization对象.
以User为根,通过基本的getters方法,可以访问到此根对象的其它关联对象.【对象图的导航,必须通过getters方法导航】
注意:    * 导航的目的,就是为了获取某个对象的值或设置某个对象的值或调用某个对象的方法.
            * OGNL表达式语言的真正目的,是为了在那些不能写java代码的地方执行java代码,或者是为了更方便的执行java代码.
3.Context对象
        * 在OGNL表达式中,有可能需要访问到多个毫不相干的对象,这时候,我们需要给OGNL传递一个Map类型的对象,把表达式中需要用到的对象放到
            Map中即可.而这个Map对象称为Context
        * 要在表达式访问到context中的对象,需要使用"#对象名称"的语法规则.
        * 存在context的主要原因就是在OGNL中,不支持多个root对象,而如果需要在表达式中访问多个毫不相关的对象时,
只能通过一个Map来把这些对象统一传递给OGNL.

时间: 2024-08-09 23:38:20

Struts_ValueStack,Ognl的相关文章

Study之Ognl

使用Ognl需要导入两个包: 测试小程序: package helloWorld; import ognl.Ognl;import ognl.OgnlException; public class TestOgnl { public static void main(String[] args) {                Person person=new Person();        person.setName("Abby");        try {        

request.setAttribute(&quot;username&quot;, username);//一定要保存,OGNL才能获取${username}

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String username= request.getParameter("username"); request.setAttribute("use

ognl.OgnlException

问题描述: Action 类代码: public class Login2Action implements Action {     // 领域对象     private Users user;     public Users getUsers() {         return user;     }     public void setUsers(Users user) {         this.user = user;     }     - } 错误提示: 警告: Erro

MyBatis中的OGNL教程

MyBatis中的OGNL教程 有些人可能不知道MyBatis中使用了OGNL,有些人知道用到了OGNL却不知道在MyBatis中如何使用,本文就是讲如何在MyBatis中使用OGNL. 如果我们搜索OGNL相关的内容,通常的结果都是和Struts有关的,你肯定搜不到和MyBatis有关的,虽然和Struts中的用法类似但是换种方式理解起来就有难度. MyBatis常用OGNL表达式 e1 or e2 e1 and e2 e1 == e2,e1 eq e2 e1 != e2,e1 neq e2

Struts2配置使用参数接收,转发与重定向,多方法,ognl使用与值传递,struts标签使用

本文档包括了 (1)首先加入jar包(最小jar组合) (1)   在web.xml中注册Struts2 这是一个前控制器作用是提供一个统一的入口,所有的请求都先经过前控制器就是这里,然后由他在做进一步处理 <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

Ognl中根元素与非根元素的关系

Ognl中根元素与非根元素的关系 根元素:可以理解为全局变量 非根元素:局部变量 从两者获取其属性的方式看: Object obj = Ognl.parseExpression(“[1]”); [1]根元素:不用写#号,填写属性 非根元素:用写#号,填写对象名字 注:从填写内容能看出全局和局部了 返回得到的obj就是在全文中从上到下搜索到的[1],比如说全局和局部名称一致了,你填写属性那肯定就是全局,都没到局部那个地方就搜索到了. OgnlContext 这就是上下文.上下文干啥的,可以理解下英

Java实战之01Struts2-04拦截器、上传下载、OGNL表达式

十二.Struts2中的拦截器 1.拦截器的重要性 Struts2中的很多功能都是由拦截器完成的.比如:servletConfig,staticParam,params,modelDriven等等. 是AOP编程思想的一种应用形式. 2.拦截器的执行时机: \ 3.自定义拦截器 3.1.拦截器的类试图(初级版本): 3.2.编写步骤: a.编写一个类,继承AbstractInterceptor类或者实现Interceptor接口.重写intercept方法. 1 public class MyI

OGNL表达式语言中的&quot;#&quot;和&quot;$&quot;的区别

Struts2使用标准的Context来进行OGNL表达式语言求值,OGNL的顶级对象是一个Context,这个Context对象就是一个Map类型实例,其根对象就是ValueStack,如果需要访问ValueStack里的属性,直接通过如下方式即可:    //取得ValueStack中bar属性    ${bar}除此之外,Struts2还提供了一些命名对象,但是这些命名对象都不是Stack Context的跟对象,它们只是存在于StackValue中.所以访问这些对象时需要使用“#”前缀来

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