要了解Struts2与OGNL表达式的关系,我们必须先搞清楚以下三个概念:

1、  ActionContext它是Action运行的上下文环境,Action的多项设置都存放在次,我们每一次Action调用都会创建一个ActionContext。通常情况下我们可以通过静态方法getContext()来获得Action上下文,进而进行其它操作,比如说可以得到request、session、application。

2、  ValueStack此对象主要是由OGNL框架实现,具体的实现类是com.opensymphony.xwork2.util.ValueStack;它主要包含了一个Map类型的Context对象,和最重要的getValue与findValue方法,以及peek、pop等栈所特有的方法。

Strut 2的Action类通过属性可以获得所有相关的值,如请求参数、Action配置参数、向其他Action传递属性值(通过chain结果)等等。要获得这些参数值,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在Struts2调用Action类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值。

要完成这个功能,有很大程度上,Struts 2要依赖于ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts2接收到一个.action的请求后,会先建立Action类的对象实例,并且将Action类的对象实例压入ValueStack对象中(实际上,ValueStack对象相当于一个栈),而ValueStack类的setValue和findValue方法可以设置和获得Action对象的属性值。Struts2中的某些拦截器正是通过ValueStack类的setValue方法来修改Action类的属性值的。如params拦截器用于将请求参数值映射到相对应的Action类的属性值。在params拦截器中在获得请求参数值后,会使用setValue方法设置相应的Action类的属性。

从这一点可以看出,ValueStack对象就象一个传送带,当客户端请求 .action时,Struts2在创建相对应Action对象后就将Action对象放到了ValueStack传送带上,然后ValueStack传送带会带着Action对象经过若干个拦截器,在每一拦截器中都可以通过ValueStack对象设置和获得Action对象中的属性值。实际上,这些拦截器就相当于流水线作业。如果要对Action对象进行某项加工,再加一个拦截器即可,当不需要进行这项工作时,直接将该拦截器去掉即可。

需要注意的是我们访问这类对象时是不需要加入#的,因为它是根对象,所以不能加#,加了以后就不能访问到了。比如我们在Action中做了如下操作ActionContext.getContext().getVlaueStack().setVlaue(“MM”,”这是信息”);然后在页面就可以通过<s:property value=”MM” />就可以了。

3、  Stack Context(map):stack上下文,它包含一系列对象,包括:request、session、attr、application map等,也是用来存值的。Struts2对OGNL上下文的概念又做了进一步扩充,在struts2中,OGNL上下文通常如下所示:

|--request

|--application

context map---|--OgnlValueStack(root) [ user、action、OgnlUtil、... ]

|--session

|--attr

|--parameters

在Struts2中,采用标准命名的上下文(Context)来处理OGNL表达式。处理OGNL的顶级对象是一个Map(也叫context map,它实际上是ActionContext中的一个对象,也叫context),在这个contxt属性中我们分别放置了

context.put(“常量REQUEST”,new HashMap<String,Object>());

context.put(“常量APPLICATION”,new HashMap<String,Object>());

等等,同样我们在其中也放置了一个名叫vsMap的对象(自己随便取了个名字);来看下面两个相关的方法

public void setValueStack(ValueStack stack) {  put(VALUE_STACK, stack);   }

public void put(String key, Object value) {          context.put(key, value);   }

我们可以看到这个ValueStack同样设置到了上下文对象中[实际上使用的ValueStack中的context属性]。 而ValueStack中除了这个Map以外,还维护一个ComponentRoot对象,它实际上用来存放我们的一个List集合,它还要维护一个栈即Stack, 以期让我们进行后续的操作。

Struts2框架把我们的ActionContext设置为OGNL 的上下文环境,凡是此环境中的值我们都应该通过#key的方式来进行访问,所以request,session等需要加前缀,又因为Struts2将我们的ValueStack作为OGNL的根对象,所以我们访问其中的内容只能通过非#的方式来进行。Action的实例,总是放到value stack中。因为Action放在stack中,而stack是root(根对象),所以对Action中的属性的访问就可以省略#标记。但是,要访问ActionContext中其它对象的属性,就必须要带上#标记,以便让OGNL知道,不是从根对象,而是从其它对象中去寻找。具体的代码可以这样理解:

而我们直接通过ActionContet.getContext().put(“属性名”,“值”);放入的数据放在了一个ActionContext 的context对象(OGNL上下文)和ValueStack对象的context对象共同引用的一个Map对象中,所以我们既可以通过#key也可以直接通过key来进行访问。那么访问Action中的属性的代码就可以这样写:

<s:property value="postalCode"/>其它ActionContext中的非根对象属性的访问要像下面这样写:

<s:property value="#session.mySessionPropKey"/> or

<s:property value="#session['mySessionPropKey']"/> or

<s:property value="#request['myRequestPropKey']"/>对Collection的处理,内容就很简单。

<s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />这是处理List。这个代码在页面上建立一个下拉选项,内容是list中的内容,默认值是name2。

处理map

<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />

需要注意的是,判断一个值是否在collection中。我们要使用in或者not in来处理。

<s:if test="'foo' in {'foo','bar'}">

muhahaha

</s:if>

<s:else>

boo

</s:else>

另外,可以使用通配符来选择collection对象的子集。

?——所有匹配选择逻辑的元素

^——只提取符合选择逻辑的第一个元素

$——只提取符合选择逻辑的最后一个元素

person.relatives.{? #this.gender == 'male'}

设值计算

Struts2中使用OGNL进行设值计算,就是指View层传递数据到Control层,并且能够设置到相应的Java对象中。这个过程从逻辑上说需要分成两步来完成:

1、  对于每个请求,都建立一个与相应Action对应的ActionContext作为OGNL的上下文环境和ValueStack,并且把Action压入ValueStack

2、  在请求进入Action代码前,通过某种通用的机制,搜集页面上传递过来的参数,并调用OGNL相关的代码,对Action进行设值。上面的第一个步骤,在处理URL请求时完成,而第二个步骤由struts2内置的拦截器完成。

3、  “#”主要有三种用途:

  1. 访问OGNL上下文和Action上下文,# 相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:

a)         名称

b)         作用

c)         例子

  1. parameters包含当前HTTP请求参数的Map,#parameters.id[0]作用相当于request.getParameter("id")
  2. reques包含当前HttpServletRequest的属性(attribute)的Map,#request.userName相当于request.getAttribute("userName")
  3. session包含当前HttpSession的属性(attribute)的Map,#session.userName相当于session.getAttribute("userName")
  4. application包含当前应用的ServletContext的属性(attribute)的Map, #application.userName相当于application.getAttribute("userName")

4、  attr用于按request > session > application顺序访问其属性(attribute), #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止

a)         用于过滤和投影(projecting)集合,如books.{?#this.price<100};

b)         构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。

5、  “%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。[既字符串不是输出到页面,而是作为某个属性的取值],如下面的url就是一个取值。

例如在Ognl.jsp中加入以下代码:

<h3>%的用途</h3>

<p><s:url value="#foobar['foo1']" /></p>

<p><s:url value="%{#foobar['foo1']}" /></p>

6、  $符号主要有两个方面的用途。

a)         在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息 : 年龄必须在${min}同${max}之间。

b)         在Struts 2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:

<validators>

<field name=”intb”>

<field-validator type=”int”>

<param name=”min”>10</param>

<param name=”max”>100</param>

<message>BAction-test校验:数字必须为${min}为${max}之间!</message>

</field-validator>

</field>

</validators>

浅析Struts2中的OGNL和ValueStack的更多相关文章

  1. [转]STRUTS2中的OGNL

    OGNL表达式是(Object-Graph Navigation Language)是对象图形化导航语言.OGNL是一个开源的项目,struts2中默认使用OGNL表达式语言来显示数据.与serlve ...

  2. Struts2中的OGNL表达式

    一.OGNL表达式简介 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.所谓对象图,即以任意一个对象为根,通过OGNL可以访问 ...

  3. struts2中,OGNL访问值栈的时候查找的顺序是什么?请排序:模型对象、临时对象、固定名称的对象、Action对象

    struts2中,OGNL访问值栈的时候查找的顺序是什么?请排序:模型对象.临时对象.固定名称的对象.Action对象 解答:struts2的值栈排列顺序为:1).临时对象:2).模型对象:3).Ac ...

  4. struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值

    在Struts2中,一个请求在终于到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是 ...

  5. struts2中的OGNL详解

    先了解一下OGNL的概念 OGNL的全名称Object Graph Navigation Language.全称为对象图导航语言,是一种表达式语言.使用这种表达式语言,你可以通过某种表达式语法,存取J ...

  6. Struts2中使用OGNL

    链接:Struts标签库 OGNL(Object Graphic Navigatino Language) OGNL称为对象图导航语言.以一个对象为根(起点),通过OGNL可以访问与这个对象关联的其它 ...

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

    1,Struts2框架主要组件的处理流程 在说ValueStack之前,笔者先说一说Struts2中常用的组件,struts2中常用组件有strutsPrepareAndExecuteExceptio ...

  8. Struts2中的OGNL详解 《转》

    首先了解下OGNL的概念: OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的 ...

  9. (补充)9.Struts2中的OGNL表达式

    OGNL表达式概述 1. OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写 * 所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关 ...

随机推荐

  1. OpenCV探索之路(二十六):如何去除票据上的印章

    最近在做票据的识别的编码工作时遇到一些问题,就是票据上往往会有一些红色印章把一些重要信息区域给覆盖了,比如一些开发票人员盖印章时比较随意,容易吧一些关键区域给遮蔽了,这让接下来的票据识别很困难,因此, ...

  2. 实现径向变换用于样本增强《Training Neural Networks with Very Little Data-A Draft》

    背景: 做大规模机器学习算法,特别是神经网络最怕什么--没有数据!!没有数据意味着,机器学不会,人工不智能!通常使用样本增强来扩充数据一直都是解决这个问题的一个好方法. 最近的一篇论文<Trai ...

  3. YYHS-Super Big Stupid Cross(二分+扫描线+平衡树)

    题目描述 “我是超级大沙茶”——Mato_No1 为了证明自己是一个超级大沙茶,Mato 神犇决定展示自己对叉(十字型)有多么的了 解. Mato 神犇有一个平面直角坐标系,上面有一些线段,保证这些线 ...

  4. ASP.NET没有魔法——ASP.NET MVC 与数据库之EntityFramework配置与连接字符串

    前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置.连接字符串的指定仍然存在一些疑问. 本章将对EF的配置进行介绍. EF可以通过两种方式来实现配置,分别是代码方 ...

  5. asp.net中kindeditor配置

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>KindEditor< ...

  6. WPF DataGrid自动生成行号

      在使用WPF进行应用程序的开发时,经常会为DataGrid生成行号,这里主要介绍一下生成行号的方法.通常有三种方法,这里主要介绍其中的两种,另一种简单提一下. 1. 直接在LoadingRow事件 ...

  7. javascript-OOP基础详解

      前  言 S     N 今天给大家详解一下面向对象编程(简称OOP)基础,OOP 语言使我们有能力定义自己的对象和变量类型 .对象拥有属性和方法 . 所以今天就给大家详解对象和类 . 1-1简介 ...

  8. YYHS-NOIP模拟赛-mine

    题解 这道题不难想到用dp来做 dp[i][0]表示第i个格子放0 dp[i][1]表示第i个格子放1且第i-1个格子放雷 dp[i][2]表示第i个格子放2 dp[i][3]表示第i个格子放1且第i ...

  9. 【node】使用nvm管理node版本

    写在前面 nvm(nodejs version manager)是nodejs的管理工具,如果你想快速更新node版本,并且不覆盖之前的版本:或者想要在不同的node版本之间进行切换: 使用nvm来安 ...

  10. Eratosthenes,筛法求素数

    //筛法求区间[0,n]的所有素数,v为素数表 //v[i]==0,i为素数 void f(int n) { int m=sqrt(n+0.5); memset(v,,sizeof(v)); ;i&l ...