Struts2.x教程(二) OGNL和值栈

一、OGNL是什么

OGNL(Object Graph Nvigation Language,对象图导航语言)是一个开源的表达式引擎。通过使用OGNL的表达式语法可以存取Java对象树的任意属性和调用Java对象树的方法等。

我们通过一个示例来了解OGNL。

分别创建三个实体类(全部省略了getter、setter方法):

//学生类

public class Student {

private String name;

private Integer age;

private Grade grade;

}

//班级类

public class Grade {

private String name;

private Teacher teacher;

}

//老师类

public class Teacher {

private String name;

}

根据上面三个实体对象的引用,可以形成一个这样的依赖图:

student

|--name

|--grade

|--name

|--teacher

|--name

通过这样的依赖关系图,可以根据student对象导航到grade对象,继而通过grade对象导航到teacher对象。通过Java代码获取如下:

String teacherName = student.getGrade().getTeacher().getName();

对象图就是指对象的依赖关系图,导航就是指根据依赖关系的一个对象定位过程。

那么,我们来看OGNL是如何使用表达式语言来完成导航操作的:

//取值表达式,都是基于对象的getter方法进行导航的

String teachName = (String)Ognl.getValue("grade.teacher.name", student);

二、OGNL的基本操作

1、OGNL的三个要素

Ognl的getValue有两个参数:

第一个参数是表达式。

表达式是整个OGNL的核心,所有OGNL操作都是针对表达式解析后进行的。它表明了此次OGNL操作要“做什么”。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。

OGNL支持大量的表达式语法,不仅支持这种“链式”猫鼠对象访问路径,还支持在表达式中进行简单的计算。

第二个参数是Root对象。

Root对象也就是操作对象。表达式规定了“做什么”,而Root对象则规定了“对谁操作”。

而实际上OGNL的取值还需要一个上下文环境。

设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,那么Root对象放在哪里,OGNL又在哪里对它进行的操作呢?这个操作对象所在环境就是OGNL的上下文环境(Context)。上下文环境规定了OGNL的操作“在哪里进行”。

OGNL的上下文环境就是OgnlContext,它是一个Map结构的类,并且OGNL支持使用Map来构建一个OGNL的上下文环境。这样我们除了Root对象,还可以从上下文环境中获取各类对象。

例如,下面的代码示例:

Student s1 = new Student("student1");

Student s2 = new Student("student2");

Student s3 = new Student("student3");

Map context = new HashMap();

context.put("s1", s1);

context.put("s2", s2);

String names = (String)Ognl.getValue("#s1.name+‘,‘+#s2.name+‘,‘+name", context, s3 );

输出:

student1,student2,student3

2、对Root对象和上下文环境的访问

对于Root对象的访问,表达式可以直接写Root对象属性。而要访问上下文环境中的对象,表达式中要通过#来访问。

比如获取上下文环境中的s1和s2对象,就需要在前面加上#来访问。而访问Root对象(s3),可以直接使用name。

在前面第一个例子中,只设置了Root对象参数,OGNL会构建一个默认的上下文环境,并将Root对象以key=root的形式存储在上下文环境中。

所以,我们也可以这样获取:

String teachName = (String)Ognl.getValue("#root.grade.teacher.name", student);

3、方法调用

OGNL的方法调用表达式和Java的方法调用非常相似,通过"对象.方法()"就可以完成调用,并且可以传递参数。

示例:

String gradeName = (String)Ognl.getValue("grade.getName()", student);

4、对静态变量的访问

使用OGNL访问静态变量的表达式语法是:@[class]@[field/method]。注意class需要是完整类名,也就是说需要包含包名。

示例:

//访问com.boya.struts2.util.Constant类中名为SCHOOLNAME的属性值

@[email protected]

//调用com.boya.struts2.util.Constant类中名为get的方法

@[email protected](‘key‘)

5、使用操作符进行简单计算

OGNL支持的操作符基本和Java里的操作符一样,除了+、-、*、/、++、--、==之外,还支持mod、in、not in等。

2+5    //加

‘hello‘+‘world‘ //字符串连接

5 mod 2 //取模

i++ //递增

s in list //判断对象是否在集合中

6、访问数组和容器

OGNL支持以数组下标的方式访问数组,也可以用于List集合。对于Map集合,同样支持根据key值进行访问。

//访问grade中的学生集合的第一个对象的name

grade.students[0].name

//根据key值访问map

map[‘key‘]

7、集合操作的投影和选择

OGNL支持类似数据库操作的投影和选择功能。

就像Hibernate的投影查询一样,可以使用这样的语法:collection.{attrName}来返回指定属性值的集合

选择就是对集合的过滤,语法为:collection.{X expression},其中X是一个选择操作符,expression则为过滤用的逻辑表达式。选择操作符有三种:

? 返回满足条件的所有元素

^ 返回满足条件的第一个元素

$ 返回满足条件的最后一个元素

示例:

//返回grade对象中students集合里面那么属性构成的集合

grade.students.{name}

//返回grade对象中students集合里面name不为null的元素构成的集合

grade.students.{? #this.name!=null}

8、构造对象

OGNL支持通过表达式来构造对象。构造方式主要有三种:

a、构造List:使用{},元素之间使用逗号(,)进行分隔

b、构造Map:使用#{},key-value直接使用冒号分隔,每组键值对使用逗号分隔

c、构造对象:直接使用对象的构造函数构造

示例:

//构造List

{‘a‘,‘b‘,‘c‘}

//构造Map

#{‘key1‘:‘value1‘,‘key2‘:‘value2‘}

//构造对象(必须使用完整类名)

new com.boya.struts2.entity.Student(‘boya‘)

三、#、%、$符号在OGNL的用途总结

1、#符号的三种用途

a、加在普通OGNL表达式前面,用于访问OGNL上下文环境中的变量

b、使用#{}语法,用于构造Map

c、#this表示对this指针的引用

2、%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。

示例:

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

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

3、$符号有两个主要的用途:

a、用于在国际化资源文件中,引用OGNL表达式

b、在Struts 2配置文件中,引用OGNL表达式,如

<action name="AddPhoto" class="addPhoto">

<interceptor-ref name="fileUploadStack" />

<result type="redirect">ListPhotos.action?albumId=${albumId}</result>

</action>

四、ValueStack介绍

Struts1的Action是依赖容器的,Action中就封装了web容器对象,比如request、response等。而Struts2的Action已经彻底的脱离容器,但是我们提交一个Action,这个Action还是需要和web容器进行交互的,Struts2是构造了一个Action的上下文环境,称之为ActionContext,它封装了当前的Action以及与web容器交互的requst、response等对象。并且使用ThreadLoacl模式对每一次请求对会实例话一个新的ActionContext与当前线程绑定,也正因此Struts2的action是线程安全的(和我们见过的Hibernate对Session的封装一样)。

可以说ActionContext封装一个处理web请求的环境,而在这个环境中对请求数据存储传输则是交给了ValueStatic。

ValueStack,被称为值栈,是对OGNL的扩展,Struts2正式通过ValueStack来使用OGNL进行赋值和取值操作的。

ValueStack对OGNL做了怎样的扩展呢?它不仅封装了OGNL的所有功能,并且主要对OGNL的Root对象进行了扩展。ValueStack封装了一个CompoundRoot类型的对象作为root属性,CompoundRoot是一个继承ArrayList的栈存储结构。而所有被压入栈中的对象,都会被视为OGNL的Root对象。在使用OGNL计算表达式时,首先会将栈顶元素作为Root对象,进行表达式匹配,匹配不成功则会依次向下匹配,最后返回第一个成功匹配的表达式计算结果。

因此,Struts2通过ValueStack实现了多Root对象的OGNL操作。

当你提交一个请求,会为这个请求创建一个和web容器交互的ActionContext,与此同时会创建ValueStack,并置于ActionContext之中。而实例化Action之后,就会将这个action对象压入ValueStack中。

在请求“映射“过程中,Struts2则是通过ParametersInterceptor拦截器将提交的参数值封装入对应的Action属性中。

因此action实例可以作为OGNL的Root对象,对于Action中的属性、方法都可以使用OGNL来获取。

我们通过一个示例来演示一下Struts2如何通过ValueStack操作数据。

1、先写一个简单的UserAction,其中只有一个name属性:

public class UserAction extends ActionSupport{

private String name;

public String execute(){

System.out.println(this.name);

return "success";

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

2、我们直接通过get方式请求,将参数传递给Action:

http://localhost:8080/struts2-ognl/user?name=boya

3、请求传递的参数值,会自动封装入name属性中,在execute方法中可以直接获得这个属性值。

4、请求返回jsp页面,使用Struts2的taglib获取

Name:<s:property value="name"/>

Struts2 Ognl示例:http://download.csdn.net/detail/boyazuo/7706001

Struts2.x教程(二) OGNL和值栈

时间: 2024-10-08 00:07:41

Struts2.x教程(二) OGNL和值栈的相关文章

Struts2 (三) — OGNL与值栈

一.OGNL表达式 1.概述 1.1什么是OGNL ? OGNL是Object-Graph Navigation Language的缩写,俗称对象图导航语言. 它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能. ? Eg: hibernate 查询方式 : 对象导航查询. ? 其实就是查询出来了一个对象之后,通过对象里面的getXXX() 来获取关联的对象. ? 它是一个开源项目,并不是struts发明

OGNL与值栈

一.OGNL入门 1.什么是OGNL OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言.使用这种表达式语言,可以通过使用某种表达式语言,来存取Java对象的任意属性,调用Java的方法,同时能够自动实现必要的数据类型转换, 2.OGNL的作用 Struts2默认的表达式语言就是ognl表达式语言,该语句具有以下的特点 支持对象方法的调用.例如:objectName.methodName(). 支持静态方法调用和值

框架学习之Struts2(三)---OGNL和值栈

一.OGNL概述 1.1OGNL是对象图导航语言(Object-Graph Navigation Languaged)的缩写,他是一种功能强大的表达式语言,通过简单一致的表达式语法,可以存取Java对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型的转化功能.他使用相同的表达式去存取对象的属性.如果吧表达式看作一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与java对象之间沟通的桥梁. 1.2OGNL的要素 表达式:表达式是整个OGNL的核心,OGNL会根据表达式去对

OGNL表达式&amp;值栈&amp;拦截器

OGNL 什么是ognl OGNL是Object-Graph Navigation Language的缩写,对象图导航语言. 他并不是Struts2的一部分,他只是经常和Struts2一起使用 ognl有啥作用 支持对象方法的调用 支持静态方法的调用和值访问 来操作值栈中的数据,访问OGNL上下文和ActionContext 操作集合对象 ognl的要素 Root对象 Context对象 值栈 什么是值栈 Struts2将XWork对Ognl的扩展这一套机制封装起来,这个对象叫ValueStac

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

Struts工作机制图+OGNL+EL+值栈(Map,对象栈)

struts 值栈  通过get set方法 方便的获取,设置属性值      比如从jsp页面传来的參数...从Action设置jsp所要回显的内容 注意EL表达式,struts2对request进行了封装,所以它的查找顺序 多了一个findvalue() 如上图 再看以下的代码: public class UserAction { private String username; //查看用户的具体信息 public String detail(){ username = "张三"

struts2值栈存取数据小结(使用ognl表达式)

前言:使用ognl和struts2标签库的时候要在 jsp页面 中 加入这么一行 <%@ taglib uri="/struts-tags" prefix="s" %> struts(统一格式): <action name="ognl" class="com.demo.test1.OnglAction" method="ognl1"> <result name="og

关于Struts2中的值栈与OGNL表达式

1.1.1    OGNL概述: Object Graphic Navigation Language(对象图导航语言)的缩写 * EL     :OGNL比EL功能强大很多倍. 它是一个开源项目. Struts2框架使用OGNL作为默认的表达式语言. OGNL相对其它表达式语言具有下面几大优势: 1.支持对象方法调用,如xxx.doSomeSpecial(): 2.支持类静态的方法调用和值访问,表达式的格式: @[类全名(包括包路径)]@[方法名 |  值名],例如: @[email prot

Struts2中的值栈

一 什么是值栈 值栈: struts2中提供的一种类似于域对象的工具, 用于struts2中的存值和取值. 每次访问Action的时候, 都会创建一个action对象, 而每个action对象中都存在一个值栈对象 值栈对象的声明周期与Action的生命周期(第一次访问action的时候被创建, 当action中方法返回值时被销毁)一致. 二 Action中值栈对象的获取方法 1. 通过ActionContext对象获取 ActionContext context = ActionContext.