Struts_ValueStack,Ognl

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.

以上是关于Struts_ValueStack,Ognl的主要内容,如果未能解决你的问题,请参考以下文章