ognl表达式、值栈、actionContext之间的关系

来源:互联网 发布:国际空间站软件 编辑:程序博客网 时间:2024/06/03 15:56

转载:
http://www.cnblogs.com/whgk/p/6600393.html
http://blog.csdn.net/qq924862077/article/details/49914033

一、什么是Ognl?

   通过百度百科查询到的解释,其中详细的说明了OGNL的作用。
      这里写图片描述
   下面我们就对OGNL这5个作用进行讲解

   1、存取对象的任意属性,简单说就是对javabean进行操作(重要)

   2、调用对象方法。

   3、调用类的静态方法

   4、索引数组元素

   5、操作集合(重 要)

二、OGNL的功能实现

  操作之前必须知道如何使用OGNL表达式,并且了解OGNL表达式的取值范围只能在其context和root中,格式为:

    Ognl.getValue(expression,context,root);

    //expression:为我们编写的ognl表达式,从后两个参数中获取值,获取规则会从下面的例子中详细讲解

    //context:ognl的上下文,类型为map,

    //root:ognl的根,可以为javabean、list、map、…. 等等很多值

2.1、对javabean进行操作

  User.java
 这里写图片描述
 
 Address.java
 这里写图片描述
 
 获取javabean中的属性值
 这里写图片描述

 获取javabean中的对象的属性值
 这里写图片描述
 
 对javabean中的属性进行赋值操作
 这里写图片描述

2.2、调用对象方法

这里写图片描述

2.3、调用类的静态方法或属性

这里写图片描述

2.4、索引数组元素

这里写图片描述

2.5、操作集合

 操作list集合,list结合本质就是一个数组,所以从list中读取数据跟对数组的操作是一样的。

这里写图片描述

 操作map集合
 
这里写图片描述

 创建list集合
 
这里写图片描述

 创建map集合
 这里写图片描述

2.6、其他用法,

  使用数学运算符,使用“,”号连接表达式,in与not in运算符,投影、过滤等操作就不讲解了,都非常简单,重点掌握上面的即可。  

三、OGNL与struts2的结合

  上面说了那么一大堆的OGNL的使用功能,我们也感受到了他的强大,啥都能取出来,表达式啥都能做,但是在struts2中它是如何使用的呢?

   OGNL中的上下文即struts2中的actionContext

   OGNL中的root即struts2中的valueStack

   actionContext和valueStack是什么,他们之间什么关系?

3.1、ActionContext和valueStack(重要)

  ActionContext:

  充当OGNL的context。是action的上下文,也可以叫做action的数据中心,本质是一个map,在其中,所有的数据都存放在这里,那其中到底存放了哪些东西呢,actionContext中存放数据的方式又是怎样的?

  actionContext是一个map,所以其中都是以键值对的形式存储对象,如下图所示,

  request、session、application这种我们熟知的作用域,注意是作用域,而不是对象,

  paramters:这个是表单提交的参数,全部都会放到这个map中,

  attr(attributes):三个作用域所有的属性都会放在该map下,如果有重复的,那么以request域中的为准。
  
  VALUE_STACK:值栈,存放着valueStack对象,也就是说,通过ActionContext能够获取到valueStack。

如果我们使用actionContext.put(); 那么会将该键值对直接放入到ActionContext下,

                
  注意:除了request外,其他都可以直接通过getXxx()获得。而想要获取request作用域,必须通过key值的方式来获取。ActionContext.getContext().get(“request”); 为什么这样呢?因为struts2对request进行了增强。从这里actionContext中是不能直接获取到的,request进行了怎样的增强呢?比如在actionContext中put了一个普通的key和value,该键值对并没有在request域中,但是在jsp中,通过在request域查找key,也能找到该键值对,底层进行了两步:第一步:从request域中查找数据,第二步:如果没有找到,将从值栈中执行findValue()。  这样就解释了为什么通过ActionContext不能直接获取request,并且为什么不在request作用域中的数据,而通过在request域中查找也能够获取到。
  
这里写图片描述这里写图片描述

valueStack:值栈,本质是一个ArrayList,作用,充当ognl的root,给一次请求中共享数据的功能。

 内部图

这里写图片描述

  root:源码中的名称为CompoundRoot,它也是一个栈,而每次值栈中入栈和出栈等操作其实就是对CompoundRoot进行对应的操作。

  Context:对actionContext的引用,也就是通过valueStack也能够获取到上下文,通过getContext();

  在我们访问一个action时,会将action加入到栈顶,也就是action会在CompoundRoot的栈顶,而我们提交的各种表单参数(充当了ognl表达式)会在valueStack从顶向下查找对应的属性进行赋值。这就是值栈的作用。

  值栈的操作

  这里提一下,知道了值栈的内部结构图,那么就好理解了。

  action中手动向valueStack中放数据。

  ActionContext.getContext().getValueStack().push(xxx);  //一般是javabean,这样放是放在root中,因为push操作是对栈进行操作,也就是对root进行操作

  ActionContext.getContext().getValueStack().set(key,value);  //任意值,以key-value的形式放入到了root中。

  jsp获取

  push存放,在root下,直接使用属性获取即可

  set存放,通过属性也可以直接获得。这里要排除一个误区,就是不要觉得set方式是以键值对的方式存放,就觉得是放入了context中,并没有,还是在root中锝

  context操作

  ActionContext.getContext().put(key,value);  //存放在actionContext中,也就是OGNL的context中

  JSP获取:三种方式进行获取

  #key获取。  

  直接使用key获取,因为值栈中也有context。只不过要从栈顶中的root开始找,然后在从context中查找

  #request获取。因为struts2对request进行了增强,如果request域中找不到,则使用findValue(),从值栈中的root开始一路往下找。
  

3.2、ActionContext和valueStack的关系(重要)      

  你中有我,我中有你。
  这里写图片描述
  
  也就是说,通过valueStack可以获取到actionContext,通过ActionContext也可以获取到valueStack。

  valueStack是对root进行操作,而actionContext是对context进行操作。(root和context是OGNL中的根和上下文)

获取值栈的方式:

    ActionContext.getContext.getValueStack();//常用

    ActionContext.getContext.get(“VALUE_STACK”);

    request.getAttribute(“VALUE_STACK”);    //这个为什么可以?因为request进行了增强。详情看上面的解释。

获取actionContext的方式

    ActionContext.getContext();  //常用
    valueStack.getContext();

3.3、struts2不同的地方使用OGNL表达式获取数据

3.3.4、在jsp页面中

  部分都会在这里使用,因为jsp就是显示数据的地方,在struts2中有很多s标签,通过s标签和OGNL表达式一起配置使用,就能拿到想要的数据了。而OGNL的表达式的编写在最开始就已经讲解过了,context就是actionContext,root就是valueStack,剩下表达式就看我们需要什么了。标签的讲解会在下一章

3.3.5、在struts.xml中

  在struts.xml中有时候也需要用到OGNL表达式去拿一些数据。比如,在result中设置stream时,就需要从action中获取流,而action可以看成是javabean,又在栈顶,所以直接使用OGNL表达式就能够获取到,但是注意特殊的,如果在你直接编写ognl表达式时struts2不能够区分出这是ognl表达式还是普通文本,那么就需要使用${}来表明该段文本是ognl表达式
  这里写图片描述

四、总结

   struts2我觉得最重要的两点,

   一、理解它的架构图,知道大概的流程,
   
   二、该篇文章讲解的值栈,actionContext,ognl的关系,

ValueStack

(1)ValueStack是一个借口,在Struts2中使用OGNL表达式实际上是使用实现了ValueStack接口类的OgnlValueStack,它是ValueStack的默认实现类。
(2)ValueStack贯穿整个action的生命周期,每一个action实例都拥有一个ValueStack对象,其中保存了当前action对象和其他相关对象。
(3)struts2把ValueStack对象保存在名为struts.valueStack的request域中,ValueStack作用域为request,当action创建的时候,ValueStack就创建了,action被销毁时,ValueSatck就销毁。当struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action,然后把action压入到值栈中,所以action的实例变量可以被ognl访问
(4)ValueStack中的数据分两部分存放:root(栈结构,CompoundRoot)和context(map形式,OgnlContext)
1)、其中的root是CompoundRoot,继承了ArrayList,提供了push和pop方法。一个请求在最终到达Action的方法之前,Action对象本身会被压入到ValueStack(实际上放到CompoundRoot中),所以action对象是CompoundRoot中的一个元素。
2)、其中的context对象是OGNLContext,它实现了map接口,在valueStack的默认实现类中,OgnlValueStack中调用OGNL方法,返回一个OgnlContext对象。
(5)获取ValueStack的三种方式:
1)、ValueStack valuestack=ActionContext()。getValueStack(); ActionContext为action的上下文,其中有重要的6大对象(valuestack,request,session,application,parameter,attr),ognl表达式必须选择ActionContext中的一个对象作为跟对象(root),默认为ValueStack,因此访问ValueStack中数据不加#,而如果要使用另外5个对象作为根对象,需要加#前缀。
2)、ValueStack valuestack=ServletActionContext.getValueSatck(ServletActionContext.getRequest());
ServletActionContext继承了ActionContext,它与web容器耦合,可以获得web容器的一些信息。
3)、ValueStack valuestack=(ValueStack) ServletActionContext.getRequest().getAttribute(“struts.valueStack”);

OGNL类图

列表内容

这里写图片描述

ValueStack内存结构图:

这里写图片描述

阅读全文
0 0