`
阅读更多

先让我们花费1分钟的时间来简单思考一个问题,MVC这3者之间,到底是通过什么真正融合起来的?

有人说是Controller,因为它是核心控制器,没有Controller,MVC就无从谈起,失去了职责划分的原本初衷。也有人说是View,因为所有的需求都是页面驱动的,没有页面,就没有请求,没有请求,也谈不上控制器和数据模型。

个人观点:贯穿MVC模型之间起到粘合剂作用的是数据。数据在View层成为了展示的内容,而在Controller层,成为了操作的载体,所以数据是整个MVC的核心。

流转的数据

无论MVC三者之间的粘合剂到底是什么,数据在各个层次之间进行流转是一个不争的事实。而这种流转,也就会面临一些困境,这些困境,是由于数据在不同世界中的表现形式不同而造成的:

1. 数据在页面上是一个扁平的,不带数据类型的字符串,无论你的数据结构有多复杂,数据类型有多丰富,到了展示的时候,全都一视同仁的成为字符串在页面上展现出来。

2. 数据在Java世界中可以表现为丰富的数据结构和数据类型,你可以自行定义你喜欢的类,在类与类之间进行继承、嵌套。我们通常会把这种模型称之为复杂的对象树。

此时,如果数据在页面和Java世界中互相流转传递,就会显得不匹配。所以也就引出了几个需要解决的问题:

1. 当数据从View层传递到Controller层时,我们应该保证一个扁平而分散在各处的数据集合能以一定的规则设置到Java世界中的对象树中去。同时,能够聪明的进行由字符串类型到Java中各个类型的转化。

2. 当数据从Controller层传递到View层时,我们应该保证在View层能够以某些简易的规则对对象树进行访问。同时,在一定程度上控制对象树中的数据的显示格式。

如果我们稍微深入一些来思考这个问题,我们就会发现,解决数据由于表现形式的不同而发生流转不匹配的问题对我们来说其实并不陌生。同样的问题会发生在Java世界与数据库世界中,面对这种对象与关系模型的不匹配,我们采用的解决方法是使用ORM框架,例如Hibernate,iBatis等等。那么现在,在Web层同样也发生了不匹配,所以我们也需要使用一些工具来帮助我们解决问题。

在这里,我们主要讨论的,是数据从View层传递到Controller层时的解决方案,而数据从Controller层传递到View层的解决方案,我们将在Struts2的Result章节重点讨论。

OGNL —— 完美的催化剂

为了解决数据从View层传递到Controller层时的不匹配性,Struts2采纳了XWork的OGNL方案。并且在OGNL的基础上,构建了OGNLValueStack的机制,从而比较完美的解决了数据流转中的不匹配性。

OGNL(Object Graph Navigation Language),是一种表达式语言。使用这种表达式语言,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java对象树的方法、同时能够自动实现必要的类型转化。如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

如何使用OGNL

让我们先研究一下OGNL的API,他来自于Ognl的静态方法:

Java代码 复制代码
  1.   
  2. /**  
  3.  * Evaluates the given OGNL expression tree to extract a value from the given root  
  4.  * object. The default context is set for the given context and root via  
  5.  * <CODE>addDefaultContext()</CODE>.  
  6.  *  
  7.  * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()  
  8.  * @param context the naming context for the evaluation  
  9.  * @param root the root object for the OGNL expression  
  10.  * @return the result of evaluating the expression  
  11.  * @throws MethodFailedException if the expression called a method which failed  
  12.  * @throws NoSuchPropertyException if the expression referred to a nonexistent property  
  13.  * @throws InappropriateExpressionException if the expression can't be used in this context  
  14.  * @throws OgnlException if there is a pathological environmental problem  
  15.  */  
  16. public static Object getValue( Object tree, Map context, Object root ) throws OgnlException;   
  17.   
  18. /**  
  19.  * Evaluates the given OGNL expression tree to insert a value into the object graph  
  20.  * rooted at the given root object.  The default context is set for the given  
  21.  * context and root via <CODE>addDefaultContext()</CODE>.  
  22.  *  
  23.  * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()  
  24.  * @param context the naming context for the evaluation  
  25.  * @param root the root object for the OGNL expression  
  26.  * @param value the value to insert into the object graph  
  27.  * @throws MethodFailedException if the expression called a method which failed  
  28.  * @throws NoSuchPropertyException if the expression referred to a nonexistent property  
  29.  * @throws InappropriateExpressionException if the expression can't be used in this context  
  30.  * @throws OgnlException if there is a pathological environmental problem  
  31.  */  
  32. public static void setValue( Object tree, Map context, Object root, Object value ) throws OgnlException  
/**
 * Evaluates the given OGNL expression tree to extract a value from the given root
 * object. The default context is set for the given context and root via
 * <CODE>addDefaultContext()</CODE>.
 *
 * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
 * @param context the naming context for the evaluation
 * @param root the root object for the OGNL expression
 * @return the result of evaluating the expression
 * @throws MethodFailedException if the expression called a method which failed
 * @throws NoSuchPropertyException if the expression referred to a nonexistent property
 * @throws InappropriateExpressionException if the expression can't be used in this context
 * @throws OgnlException if there is a pathological environmental problem
 */
public static Object getValue( Object tree, Map context, Object root ) throws OgnlException;

/**
 * Evaluates the given OGNL expression tree to insert a value into the object graph
 * rooted at the given root object.  The default context is set for the given
 * context and root via <CODE>addDefaultContext()</CODE>.
 *
 * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
 * @param context the naming context for the evaluation
 * @param root the root object for the OGNL expression
 * @param value the value to insert into the object graph
 * @throws MethodFailedException if the expression called a method which failed
 * @throws NoSuchPropertyException if the expression referred to a nonexistent property
 * @throws InappropriateExpressionException if the expression can't be used in this context
 * @throws OgnlException if there is a pathological environmental problem
 */
public static void setValue( Object tree, Map context, Object root, Object value ) throws OgnlException



我们可以看到,OGNL的API其实相当简单,你可以通过传递三个参数来实现OGNL的一切操作。而这三个参数,被我称为OGNL的三要素。

那么运用这个API,我们能干点什么呢?跑个测试看看结果:

Java代码 复制代码
  1.   
  2. /**  
  3.  * @author Downpour  
  4.  */  
  5. public class User {   
  6.        
  7.     private Integer id;   
  8.        
  9.     private String name;   
  10.        
  11.     private Department department = new Department();   
  12.        
  13.     public User() {   
  14.            
  15.     }   
  16.            
  17.         // setter and getters   
  18. }   
  19.   
  20. //=========================================================================   
  21.   
  22. /**  
  23.  * @author Downpour  
  24.  */  
  25. public class Department {   
  26.        
  27.     private Integer id;   
  28.        
  29.     private String name;   
  30.        
  31.     public Department() {   
  32.            
  33.     }   
  34.            
  35.         // setter and getters   
  36. }   
  37.   
  38. //=========================================================================   
  39.   
  40. /**  
  41.  * @author Downpour  
  42.  */  
  43. public class OGNLTestCase extends TestCase {   
  44.        
  45.     /**  
  46.      *   
  47.      * @throws Exception  
  48.      */  
  49.     @SuppressWarnings("unchecked")   
  50.     @Test  
  51.     public void testGetValue() throws Exception {   
  52.            
  53.         // Create root object   
  54.         User user = new User();   
  55.         user.setId(1);   
  56.         user.setName("downpour");   
  57.   
  58.         // Create context   
  59.         Map context = new HashMap();   
  60.         context.put("introduction","My name is ");   
  61.            
  62.         // Test to directly get value from root object, with no context   
  63.         Object name = Ognl.getValue(Ognl.parseExpression("name"), user);   
  64.         assertEquals("downpour",name);   
  65.            
  66.         // Test to get value(parameter) from context   
  67.         Object contextValue = Ognl.getValue(Ognl.parseExpression("#introduction"), context, user);   
  68.         assertEquals("My name is ", contextValue);   
  69.            
  70.         // Test to get value and parameter from root object and context   
  71.         Object hello = Ognl.getValue(Ognl.parseExpression("#introduction + name"), context, user);   
  72.         assertEquals("My name is downpour",hello);   
  73.                        
  74.     }   
  75.   
  76.     /**  
  77.      *   
  78.      * @throws Exception  
  79.      */  
  80.     @SuppressWarnings("unchecked")   
  81.     @Test  
  82.     public void testSetValue() throws Exception {   
  83.            
  84.         // Create root object   
  85.         User user = new User();   
  86.         user.setId(1);   
  87.         user.setName("downpour");   
  88.            
  89.                 // Set value according to the expression   
  90.         Ognl.setValue("department.name", user, "dev");   
  91.         assertEquals("dev", user.getDepartment().getName());   
  92.            
  93.     }   
  94.        
  95.   
  96. }  
/**
 * @author Downpour
 */
public class User {
	
	private Integer id;
	
	private String name;
	
	private Department department = new Department();
	
	public User() {
		
	}
        
        // setter and getters
}

//=========================================================================

/**
 * @author Downpour
 */
public class Department {
	
	private Integer id;
	
	private String name;
	
	public Department() {
		
	}
        
        // setter and getters
}

//=========================================================================

/**
 * @author Downpour
 */
public class OGNLTestCase extends TestCase {
	
	/**
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@Test
	public void testGetValue() throws Exception {
		
		// Create root object
		User user = new User();
		user.setId(1);
		user.setName("downpour");

		// Create context
		Map context = new HashMap();
		context.put("introduction","My name is ");
		
		// Test to directly get value from root object, with no context
		Object name = Ognl.getValue(Ognl.parseExpression("name"), user);
		assertEquals("downpour",name);
		
		// Test to get value(parameter) from context
		Object contextValue = Ognl.getValue(Ognl.parseExpression("#introduction"), context, user);
		assertEquals("My name is ", contextValue);
		
		// Test to get value and parameter from root object and context
		Object hello = Ognl.getValue(Ognl.parseExpression("#introduction + name"), context, user);
		assertEquals("My name is downpour",hello);
					
	}

	/**
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@Test
	public void testSetValue() throws Exception {
		
		// Create root object
		User user = new User();
		user.setId(1);
		user.setName("downpour");
		
                // Set value according to the expression
		Ognl.setValue("department.name", user, "dev");
		assertEquals("dev", user.getDepartment().getName());
		
	}
	

}



我们可以看到,简单的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 (#).



上面这段内容摘自Struts2的Reference,我把这段话总结为以下2条规则:

A) 针对根对象(Root Object)的操作,表达式是自根对象到被访问对象的某个链式操作的字符串表示。
B) 针对上下文环境(Context)的操作,表达式是自上下文环境(Context)到被访问对象的某个链式操作的字符串表示,但是必须在这个字符串的前面加上#符号,以表示与访问根对象的区别。


上面的这点区别咋看起来非常容易理解,不过一旦放到特定的环境中,就会显示出其重要性,它可以解释很多Struts2在页面展示上取值的各种复杂的表达式的现象。这一点在下一篇文章中会进行具体的分析。

OGNL三要素

我把传入OGNL的API的三个参数,称之为OGNL的三要素。OGNL的操作实际上就是围绕着这三个参数而进行的。

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与模板

我们在尝试了OGNL的基本操作并了解了OGNL的三要素之后,或许很容易把OGNL的操作与模板联系起来进行比较。在很多方面,他们也的确有着相似之处。

对于模板,会有一些普通的输出元素,也有一些模板语言特殊的符号构成的元素,这些元素一旦与具体的Java对象融合起来,就会得到我们需要的输出结果。

而OGNL看起来也是非常的类似,OGNL中的表达式就雷同于模板语言的特殊符号,目的是针对某些Java对象进行存取。而OGNL与模板都将数据与展现分开,将数据放到某个特定的地方,具体来说,就是Java对象。只是OGNL与模板的语法结构不完全相同而已。

深入浅出OGNL

在了解了OGNL的API和基本操作以后,我们来深入到OGNL的内部来看看,挖掘一些更加深入的知识。

OGNL表达式

OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。

接下来我们就来看看一些常用的OGNL表达式:

1. 基本对象树的访问

对象树的访问就是通过使用点号将对象的引用串联起来进行。

例如:name,department.name,user.department.factory.manager.name

2. 对容器变量的访问

对容器变量的访问,通过#符号加上表达式进行。

例如:#name,#department.name,#user.department.factory.manager.name

3. 使用操作符号

OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。

4. 容器、数组、对象

OGNL支持对数组和ArrayList等容器的顺序访问:

例如:group.users[0]

同时,OGNL支持对Map的按键值查找:

例如:#session['mySessionPropKey']

不仅如此,OGNL还支持容器的构造的表达式:

例如:{"green", "red", "blue"}构造一个List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}构造一个Map

你也可以通过任意类对象的构造函数进行对象新建:

例如:new java.net.URL("http://localhost/")

5. 对静态方法或变量的访问

要引用类的静态方法和字段,他们的表达方式是一样的@class@member或者@class@method(args):

例如:@com.javaeye.core.Resource@ENABLE,@com.javaeye.core.Resource@getAllResources

6. 方法调用

直接通过类似Java的方法调用方式进行,你甚至可以传递参数:

例如:user.getName(),group.users.size(),group.containsUser(#requestUser)

7. 投影和选择



OGNL支持类似数据库中的投影(projection) 和选择(selection)。

投影就是选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。投影操作语法为 collection.{XXX},其中XXX 是这个集合中每个元素的公共属性。

例如:group.userList.{username}将获得某个group中的所有user的name的列表。

选择就是过滤满足selection 条件的集合元素,类似于关系数据库的纪录操作。选择操作的语法为:collection.{X YYY},其中X 是一个选择操作符,后面则是选择用的逻辑表达式。而选择操作符有三种:
? 选择满足条件的所有元素
^ 选择满足条件的第一个元素
$ 选择满足条件的最后一个元素

例如:group.userList.{? #this.name != null}将获得某个group中user的name不为空的user的列表。

上述的所有的表达式,只是对OGNL所有表达式的大概的一个概括,除此之外,OGNL还有更多的表达式,例如lamba表达式等等。最具体的表达式的文档,大家可以参考OGNL自带的文档:

http://www.ognl.org/2.6.9/Documentation/html/LanguageGuide/apa.html

在撰写时,我也参考了potain同学的XWork教程以及一些网络上的一些文章,特此列出:

http://www.lifevv.com/java/doc/20071018173750030.html

http://blog.csdn.net/ice_fire2008/archive/2008/05/12/2438817.aspx

OGNLContext

OGNLContext就是OGNL的运行上下文环境。OGNLContext其实是一个Map结构,如果查看一下它的源码,就会发现,它其实实现了java.utils.Map的接口。当你在调用OGNL的取值或者设值的方法时,你可能会自己定义一个Context,并且将它传递给方法。事实上,你所传递进去的这个Context,会在OGNL内部被转化成OGNLContext,而你传递进去的所有的键值对,也会被OGNLContext接管维护,这里有点类似一个装饰器,向你屏蔽了一些其内部的实现机理。

在OGNLContext的内部维护的东西很多,其中,我挑选2个比较重要的提一下。一个是你在调用方法时传入的Context,它会被维护在OGNL内部,并且作为存取变量的基础依据。另外一个,是在Context内部维护了一个key为root的值,它将规定在OGNLContext进行计算时,哪个元素被指定为根对象。其在进行存取时,将会被特殊对待。

this指针

我们知道,OGNL表达式是以点进行串联的一个字符串链式表达式。而这个表达式在进行计算的时候,从左到右,每一次表达式计算返回的结果成为当前对象,并继续进行计算,直到得到计算结果。每次计算的中间对象都会放在一个叫做this的变量里面这个this变量就称之为this指针。

例如:group.userList.size().(#this+1).toString()

在这个例子中,#this其实就是group.userList.size()的计算结构。

使用this指针,我们就可以在OGNL表达式中进行一些简单的计算,从而完成我们的计算逻辑,而this指针在lamba表达式的引用中尤为广泛,有兴趣的读者可以深入研究OGNL自带的文档中lamba表达式的章节。

默认行为和类型转化

在我们所讲述的所有的OGNL的操作中,实际上,全部都忽略了OGNL内部帮助你完成的很多默认行为和类型转化方面的工作。

我们来看一下OGNL在进行操作初始化时候的一个函数签名:

Java代码 复制代码
  1.   
  2. /**  
  3.  * Appends the standard naming context for evaluating an OGNL expression  
  4.  * into the context given so that cached maps can be used as a context.  
  5.  *  
  6.  * @param root the root of the object graph  
  7.  * @param context the context to which OGNL context will be added.  
  8.  * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>  
  9.  *         set appropriately  
  10.  */  
  11. public static Map addDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter, MemberAccess memberAccess, Map context );  
/**
 * Appends the standard naming context for evaluating an OGNL expression
 * into the context given so that cached maps can be used as a context.
 *
 * @param root the root of the object graph
 * @param context the context to which OGNL context will be added.
 * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
 *         set appropriately
 */
public static Map addDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter, MemberAccess memberAccess, Map context );



可以看到,在初始化时,OGNL还需要额外初始化一个类型转化的接口和一些其他的信息。只不过这些默认行为,由OGNL的内部屏蔽了。

一旦需要自己定义针对某个特定类型的类型转化方式,你就需要实现TypeConverter接口,并且在OGNL中进行注册。

同时,如果需要对OGNL的许多默认行为做出改变,则需要通过设置OGNL的全局环境变量进行。

上述的这些内容,有些会在后面的章节涉及,有兴趣的读者,也可以参阅OGNL的源码和OGNL的文档寻求帮助。

分享到:
评论
1 楼 insistence 2010-05-04  
收藏!!

相关推荐

    struts2 ongl包源码

    这个压缩包包含了Struts2中的ONGL包源码,对于理解Struts2的工作原理和深入学习OGNL的使用非常有帮助。 OGNL是Object-Graph Navigation Language的缩写,它的主要功能是在对象图中导航并执行操作。在Struts2中,...

    Java struts2 ongl 标签 jsp页面

    Java Struts2 OGNL(Object-Graph Navigation Language)标签是用于在JSP页面中动态地访问和操作Java对象的强大工具。以下是对这些知识点的详细解释: 1. **对象树的访问**: OGNL允许开发者通过点号(`.`)来遍历...

    Struts2 Ongl文档

    根据提供的文件信息,我们可以归纳出以下关于Struts2中OGNL(Object-Graph Navigation Language)的知识点: ### 1. 引言与简介 OGNL 是一种强大的表达式语言,它允许开发人员通过简洁的语法来导航 Java 对象。...

    struts2中ongl表达式的使用和具体实例应用

    ### Struts2中OGNL表达式的使用与具体实例解析 #### 一、OGNL概述 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取或设置一个对象图中的属性值。它广泛应用于Struts2框架中,用于简化...

    Struts2的ONGL详解

    很好的介绍ONGL的相关知识,一看就明白,对想学习struts2或ONGL的人来说是必需的

    struts2开发工程 ongl.rar

    本工程"ongl.rar"显然是一个使用Struts2框架进行开发的项目压缩包,包含了必要的源代码和配置文件。以下是关于Struts2开发的一些关键知识点: 1. **Struts2框架核心组件**: - **Action类**:是业务逻辑的载体,...

    struts2中的ongl表达式相关简介

    ### Struts2中的OGNL表达式相关简介 #### OGNL概述 OGNL(Object-Graph Navigation Language,对象图导航语言)是Struts 2框架的默认表达式语言,它极大地增强了Struts 2的数据访问能力和代码简洁性。OGNL不仅能够...

    struts2验证+拦截器+国际化+下载excle文档+struts2二级联动+ongl表达试+ssh集成 项目下载

    struts2验证+拦截器+国际化+下载excle文档+struts2二级联动+ongl表达试+ssh集成\部分代码, 项目下载、 部分代码 请看: http://blog.csdn.net/liangrui1988/article/details/9778787

    JSTL、EL、ONGL、Struts标签的区别

    - **Struts 标签**: 提供了一组标签来简化 Struts 应用程序的开发过程,尤其是在与 Struts2 框架结合使用时更为强大。 这些技术之间可以相互配合使用,以达到更好的效果。例如,在 JSP 页面中,可以使用 JSTL 来...

    ongl的官方源代码

    本篇文章将深入探讨ongl的源代码,分析其核心概念、设计原理以及与Struts2.0框架的整合方式。 **1. oegl的基本概念** ongl的核心是它的表达式语法,它允许开发者用简洁的语句来创建和操作界面元素。例如,`${...

    Struts2学习案例--------入门篇

    输出Hello World 使用到struts2标签和jstl表达式 2、 URL:http://localhost:8080/struts100515 输入用户名XXX ------&gt; 提交 ,显示 你好 XXX 使用ONGL表达式 3、 URL:...

    struts2 详解文档

    Struts2是一个强大的Java EE应用程序框架,主要用于构建Web应用程序,特别是MVC(Model-View-Controller)架构的应用。它的核心是Action,通过Action类来处理用户的请求并返回响应。本详解文档将涵盖从Struts2的基本...

    ongl表达式

    2. **JSP标签库**:Struts提供了一系列的JSP标签,如`s:textfield`、`s:textarea`等,这些标签内部使用ONGL表达式处理数据。 3. **国际化**:在资源文件中定义国际化字符串,ONGL表达式可以引用这些字符串,实现...

    ONGL介绍

    ONGL在许多Java框架中被广泛应用,例如Struts 2、Spring等,极大地提高了开发效率和代码的可读性。 **ONGL的主要特点** 1. **动态表达式**:ONGL允许在运行时构建和执行表达式,这意味着开发者可以在不提前知道...

    在Java的Struts框架中ONGL表达式的基础使用入门

    Java的Struts框架是SSH(Spring、Struts、Hibernate)三大Web开发框架之一,而ONGNL(Object-Graph Navigation Language)则是Struts2框架中核心的表达式语言,用于数据绑定和表达式求值。本篇文章将深入解析如何在...

    ongl的使用方法及怎么解决

    **ONGL(Object-Graph Navigation Language)**是一种强大的表达式语言,常用于Struts2框架中,用于数据绑定和表达式求值。本篇文档将详细介绍ONGL在访问上下文、集合操作以及构造Map等方面的使用方法,以及如何解决...

    ongl 灵活运用

    它在Web开发领域,特别是在Struts2框架中,被广泛用来简化视图层的逻辑,允许开发者通过简洁的表达式来访问和操作对象的属性。** ### OGNL的简介 ONGL全称为Object-Graph Navigation Language,是由OpenSymphony...

    SHH整合(mysql,struts2 2.2+spring2.5+hibernate3.0,log,jquery,标签等)DEMO

    1、SHH整合 详细清晰的标准配置,主流的应用配置,struts2.2+spring2.5+hibernate3.0 2、结合MYSQL轻量级... 使用主流的JSP标签JSTL,STRUTS2 标签 ongl数据显示 是一个集成好多主流技术的两个显示数据与登陆的DEMO

    ongl源代码

    - **WebWork/Struts2**:ONGL是这两款MVC框架的默认表达式语言,用于处理动作和视图的绑定。 - **独立使用**:ONGL也可单独作为工具库,用于在任何Java程序中执行动态表达式。 通过研究jkuhnert-ognl-1483b9a的源...

    ongl源码 非常好!

    3. OGNL在Web开发中的应用:在Struts2框架中,ONGL作为默认的表达式语言,用于视图层和模型层的数据绑定。开发者可以通过OGNL表达式在JSP页面上直接访问模型数据,实现动态渲染。 4. 使用WinCVS下载ONGL源码:...

Global site tag (gtag.js) - Google Analytics