<!-- 正文开始 -->
在mvc中,数据是在各个层次之间进行流转是一个不争的事实。而这种流转,也就会面临一些困境,这些困境,是由于数据在不同世界中的表现形式不同而造成的:
1. 数据在页面上是一个扁平的,不带数据类型的字符串,无论你的数据结构有多复杂,数据类型有多丰富,到了展示的时候,全都一视同仁的成为字符串在页面上展现出来。
2. 数据在Java世界中可以表现为丰富的数据结构和数据类型,你可以自行定义你喜欢的类,在类与类之间进行继承、嵌套。我们通常会把这种模型称之为复杂的对象树。
此时,如果数据在页面和Java世界中互相流转传递,就会显得不匹配。所以也就引出了几个需要解决的问题:
1. 当数据从View层传递到Controller层时,我们应该保证一个扁平而分散在各处的数据集合能以一定的规则设置到Java世界中的对象树中去。同时,能够聪明的进行由字符串类型到Java中各个类型的转化。
2. 当数据从Controller层传递到View层时,我们应该保证在View层能够以某些简易的规则对对象树进行访问。同时,在一定程度上控制对象树中的数据的显示格式。
如果我们稍微深入一些来思考这个问题,我们就会发现,解决数据由于表现形式的不同而发生流转不匹配的问题对我们来说其实并不陌生。同样的问题会发生在Java世界与数据库世界中,面对这种对象与关系模型的不匹配,我们采用的解决方法是使用ORM框架,例如Hibernate,iBatis等等。那么现在,在Web层同样也发生了不匹配,所以我们也需要使用一些工具来帮助我们解决问题。为了解决数据从View层传递到Controller层时的不匹配性,Struts2采纳了XWork的一套完美方案。并且在此的基础上,构建了一个完美的机制,从而比较完美的解决了数据流转中的不匹配性。相信大家看到这一定猜出来了这里的完美方案和完美机制了。对,这就是OGNL方案和OGNLValueStack机制
基本概念
OGNL(Object Graph Navigation Language),是一种表达式语言。使用这种表达式语言,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java对象树的方法、同时能够自动实现必要的类型转化。如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。既然OGNL那么强大,那么让我们一起来研究一下他的API,看看如何使用OGNL.
OGNL的API看起来就是两个简单的静态方法:
public static Object getValue( Object tree, Map context, Object root ) throws OgnlException;
public static void setValue( Object tree, Map context, Object root, Object value ) throws OgnlException
我们可以看到,简单的API,就已经能够完成对各种对象树的读取和设值工作了。这也体现出OGNL的学习成本非常低。需要特别强调进行区分的,是在针对不同内容进行取值或者设值时,OGNL表达式的不同。Struts2 Reference 写道:
The Framework uses a standard naming context to evaluate OGNL expressions. The top level object dealing with OGNL is a Map (usually referred as a context map or context). OGNL has a notion of there being a root (or default) object within the context. In expression, the properties of the root object can be referenced without any special "marker" notion. References to other objects are marked with a pound sign (#).
针对上面的话,我们可以简单的理解为下面两点:
A) 针对根对象(Root Object)的操作,表达式是自根对象到被访问对象的某个链式操作的字符串表示。
B) 针对上下文环境(Context)的操作,表达式是自上下文环境(Context)到被访问对象的某个链式操作的字符串表示,但是必须在这个字符串的前面加上#符号,以表示与访问根对象的区别。
OGNL三要素:
很多人习惯上把传入OGNL的API的三个参数,称之为OGNL的三要素。OGNL的操作实际上就是围绕着这三个参数而进行的。
看下面一段测试代码:
Ognl.setValue("department.name", user2, "dev");
System.out.println(user2.getDepartment().getName());
Ognl.setValue(Ognl.parseexpression_r("department.name"), context, user2, "otherDev");
System.out.println(user2.getDepartment().getName());
1. 表达式(Expression)
表达式是整个OGNL的核心,所有的OGNL操作都是针对表达式的解析后进行的。表达式会规定此次OGNL操作到底要干什么。我们可以看到,在上面的测试中,name、department.name等都是表达式,表示取name或者department中的name的值。OGNL支持很多类型的表达式,之后我们会看到更多。
2. 根对象(Root Object)
根对象可以理解为OGNL的操作对象。在表达式规定了“干什么”以后,你还需要指定到底“对谁干”。
在上面的测试代码中,user就是根对象。这就意味着,我们需要对user这个对象去取name这个属性的值(对user这个对象去设置其中的department中的name属性值)。
3. 上下文环境(Context)
有了表达式和根对象,我们实际上已经可以使用OGNL的基本功能。例如,根据表达式对根对象进行取值或者设值工作。不过实际上,在OGNL的内部,所有的操作都会在一个特定的环境中运行,这个环境就是OGNL的上下文环境(Context)。说得再明白一些,就是这个上下文环境(Context),将规定OGNL的操作“在哪里干”。
OGNL的上下文环境是一个Map结构,称之为OgnlContext。上面我们提到的根对象(Root Object),事实上也会被加入到上下文环境中去,并且这将作为一个特殊的变量进行处理,具体就表现为针对根对象(Root Object)的存取操作的表达式是不需要增加#符号进行区分的。
OgnlContext不仅提供了OGNL的运行环境。在这其中,我们还能设置一些自定义的parameter到Context中,以便我们在进行OGNL操作的时候能够方便的使用这些parameter。不过正如我们上面反复强调的,我们在访问这些parameter时,需要使用#作为前缀才能进行。
OGNL表达式实现原理
Struts 2中的OGNL Context实现者为ActionContext,它结构示意图如下:
当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application、#session,另外OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈)。如果要访问根对象(即ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。
在struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想像的只存放单个值,而是存放一组对象。在OgnlValueStack类里有一个List类型的root变量,就是使用他存放一组对象 |--request |--application context ------|--OgnlValueStack root变量[action, OgnlUtil, ... ] |--session |--attr |--parameters,在root变量中处于第一位的对象叫栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。大家注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:<s:property value="name"/>
由于ValueStack(值栈)是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,在JSP页面可以直接通过下面的EL表达式访问ValueStack(值栈)中对象的属性: ${foo} //获得值栈中某个对象的foo属性。如果访问其他Context中的对象,由于他们不是根对象,所以在访问时,需要添加#前缀。
application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用ServletContext的getAttribute("username")。
session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")。
request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.getAttribute("userName")。
parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")。
attr对象:用于按page->request->session->application顺序访问其属性。
相关推荐
### Struts2中OGNL的概念及原理说明 #### 一、OGNL表达式的基本用法与特点 **OGNL**,即**Object Graphic Navigation Language**(对象图导航语言),是Struts2框架中用于处理对象及其属性的强大工具之一。通过...
这篇深入学习的文章主要探讨了OGNL表达式的原理和使用。 首先,我们来理解一下OGNL是什么。OGNL是一种强大的表达式语言,允许开发者通过简单的字符串表达式来访问和修改对象图。在Struts2中,OGNL用于在Action和...
本案例提供ognl使用详解,测试通过,只需解压放入自己WEB项目中,执行struts_ognl包内java文件即可(未提供jia包,若需要可以联系留言发至邮箱),若测试不好可以联系本人提供指导. Struts 2默认的表达式语言是OGNL...
在这个压缩包中,包含的是OGNL的源码和帮助文档,这对于深入理解OGNL的工作原理以及在Struts2中的应用非常有帮助。 OGNL的核心特性包括: 1. **对象导航**:OGNL允许我们通过`.`操作符来访问对象的属性,甚至可以...
在这个压缩包中,你将找到ognl的源码和最新的API文档,这将帮助你深入理解其内部工作原理和如何有效地使用它。 首先,让我们了解一下OGNL的基础概念。OGNL的核心是它的表达式,这些表达式可以解析和执行,以访问和...
在Struts2框架中,OGNL(Object-Graph Navigation Language)和EL(Expression Language)都是用于数据绑定和表达式处理的重要工具,它们在处理视图层与模型层的数据交互方面发挥着关键作用。理解这两者的差异有助于...
**OGNL的基本概念** 1. **表达式**: OGNL的核心是其表达式语言,允许我们以简洁的方式访问和操作对象的属性。例如,`person.name` 表示访问`person`对象的`name`属性。 2. **上下文(Context)**: OGNL使用一个上...
#### 一、OGNL简介与基本概念 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。它是Struts2框架中的默认表达式语言,同时也被广泛应用于其他Java环境中。OGNL支持...
OGNL(Object-Graph Navigation Language)和XWork是Struts2的核心组件,它们对于理解Struts2的工作原理至关重要。下面将详细阐述OGNL和XWork的相关知识点。 **OGNL:** OGNL是一种强大的表达式语言,它被广泛用于...
这篇博客将深入探讨OGNL在Struts2中的应用,并通过案例"TextOgnl"来展示其工作原理。 一、OGNL的基本概念 OGNL是用于Java对象图形导航的语言,它可以轻松地访问和操作复杂的对象结构。在Struts2中,OGNL主要用作视...
这些资源对于开发者来说非常宝贵,因为它们可以帮助理解OGNL的工作原理,查找和修复可能存在的问题,以及查看API文档以正确使用OGNL。 描述中的问题“struts2部分变量(变量名称为单个小写字母开头紧跟大写字母的...
camel-ognl-1.6.4.jar, camel-ognl-2.8.1.jar, com.springsource.org.ognl-2.6.9.jar, com.springsource.org.ognl-sources-2.6.9.jar, ognl-2.5.1.jar, ognl-2.6.11.jar, ognl-2.6.3.jar, ognl-2.6.5.jar, ognl-...
阅读OGNL源码可以帮助我们理解其内部工作原理,特别是对于解析器和求值器的设计,以及如何处理各种OGNL语法和操作。这将有助于我们在使用OGNL时更好地调试和优化代码。 总结,OGNL作为强大的表达式语言,其源码揭示...
**ognl源代码与API文档...通过阅读ognl的源代码和API文档,我们可以更深入地理解其工作原理,以便在实际开发中更有效地利用ognl进行数据绑定和表达式操作。对于Java开发者来说,掌握ognl能提升项目开发效率和代码质量。
### 学习OGNL在Struts2中的工作原理 #### OGNL简介 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。它是Struts2框架的一个核心特性之一,被广泛应用于框架的...
在实际开发中,理解OGNL的工作原理能让你更好地利用它进行数据绑定和表达式计算。例如,你可以根据源代码学习如何自定义OGNL的解析行为,以适应特定的应用场景。笔记中的示例和经验分享可能会帮助你避免常见的陷阱,...
**表达式语言(EL)与OGNL概述** 表达式语言(EL)是用于在Java应用程序中简洁地访问和操作对象属性...值堆栈`OgnlValueStack`作为OGNL的主要应用场景,进一步增强了表达式的实用性和效率,使得数据的传递和处理更加流畅。
在深入理解OGNL的源码之前,我们首先需要了解OGNL的基本概念和用法。 OGNL是一种强大的表达式语言,它允许动态地访问和修改对象的属性。它的主要特点包括: 1. **对象导航**:OGNL支持通过点号(`.`)和方括号(`...
OGNL上下文(OGNL Context)和Action上下文是Struts2中两个重要的概念,它们对于理解和使用OGNL表达式至关重要。 **OGNL上下文(OGNL Context)** OGNL上下文是OGNL表达式执行时的工作空间,它存储了键值对,其中键...