struts2中ActionContext对象理解

"welcome to ARTAvrilLavigne Blog"

Posted by ARTAvrilLavigne on March 10, 2018

一、什么是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集合

三、OGNL与struts2的结合

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

OGNL中的上下文即struts2中的actionContext

OGNL中的root即struts2中的valueStack

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

3.1、ActionContext和valueStack(重要)

3.1.1、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域中查找也能够获取到。

            

       

   

3.1.2、valueStack:

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中的 ValueStack

  ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础

  ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.
  Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性request中

在 ValueStack 对象的内部有两个逻辑部分:
  ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中–它是List结构作为栈
  ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中

Struts 会把下面这些映射压入 ContextMap 中
  parameters: 该 Map 中包含当前请求的请求参数
  request: 该 Map 中包含当前 request 对象中的所有属性
  session: 该 Map 中包含当前 session 对象中的所有属性
  application:该 Map 中包含当前 application 对象中的所有属性
  attr: 该 Map 按如下顺序来检索某个属性: request, session, application

二、理解OGNL上下文context

ActionContext提供了对ognl上下文对象中数据操作的方法.
OgnlValueStack 类包含两个重要的属性:一个root和一个context。
    其中root本质上是一个ArrayList.
    而context 是一个Map(更确切的说是一个OgnlContext对象)
  在这个OgnlContext对象(context)中,有一个默认的顶层对象 _root,OGNL访问context中这个默认顶层对象中的元素时,是不需要#号的,直接通过元素的名称来进行访问,而访问其他对象时,如 request、session、attr等,则需要#号引用。
  注:Struts2将OgnlValueStack的root对象赋值给了OgnlContext 中的_root对象,在OgnlValueStack的root对象中,保存着调用Action的实例,因此,在页面上通过Struts2标签访问Action 的属性时,就不需要通过#号来引用
  总结:ognl Context包含 ObjectStack属性和ContextMap属性

  当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。
注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:

三、总结

  struts2框架在解析OGNL表达式的时候,OGNL上下文context对象就是ActionContext对象,其相当于一个大大的容器,里面包含了根对象(valueSatck,其中valueStack对象就是值栈对象)与非根对象(application、session、parameters、attr)。

  OGNL表达式中访问root中元素时直接通过元素的名称来进行访问,不需要#号的。访问application、session、parameters等非根对象时,需要在表达式前面加上#前缀


みなさんのごおうえんをおねがいします~~