在 struts2 标签中是使用 OGNL 来访问对象属性或方法的,也就是访问的 ValueStack 中的值,即 OgnlValueStack。OGNL 也能让你直接访问类的静态变量和静态方法,标准写法是:
@类全限定名@静态属性或方法名,比如访问某个常量:
<s:property value="@cc.unmi.common.Constants@MY_NAME"/>
<s:property value="@cc.unmi.common.Utils.now()"/>
麻烦就是一定要写上类的全限定名称,实际应用时肯定比这个还要长,所以必须寻求一种更精练的写法。
幸好像这篇文章:Struts2 OGNL 的增强 提到了可以用:
除了使用标准的OGNL表达式访问静态字段和静态方法外,Struts2还允许你不指定完整的类名,而是通过“vs”前缀来调用保存在栈中的静态字段和静态方法。
@vs@FOO_PROPERTY
@vs@someMethod()
@vs1@someMethod()
vs表示ValueStack,如果只有vs,那么将使用栈顶对象的类;如果在vs后面跟上一个数字,那么将使用栈中指定位置处的对象类。
看似确实很精简,实际上也是。但问题是我们该怎么把自己的常量或静态方法(应该是它们所在的类) 放到 ValueStack 上呢,并且是在栈里的哪个位置呢?
OGNL 本身的规定是在它的上下文中只能有一个 root,然后 XWork/Struts2 对它衍生了,它认为在 ValueStack 中可以有多个根对象,对根对象的属性的访问可以不用 # 号。在 Struts2 的标签中对于是否该附上 # 号,也许很多人会有些迷糊。
比如对于一个简单的 Action 转向的 jsp 页面 index.jsp,在其中用 <s:debug/> 来查看一下 ValueStack: 这两个对象 IndexAction 和 DefaultTextProvider 就是 ValueStack 的根对象,所以如果要访问 IndexAction 的 locale 属性就可以直接用 <s:property value="locale"/> 来访问,而不需要用井号(#) 的方式,像 <s:property value="#some.locale"/> 来访问的。但如果 ValueStack 中多个根对象含相同的属性名,Struts2 如何知道是取哪个根对象的相应属性呢?这也难不倒 Struts2 的,它用一个特殊的 OGNL PropertyAccessor,从栈顶的对象找下去,找到为止。
想像一下,对于 ModelDriven 的 Action,我们可以直接用 <s:property value="id"/> 访问到 Action 中 model 对象的 id 属性,就是因为 Struts2 把 Action 的 model 对象放到了 ValueStack 的根位置上了,并且处理 Action 实例的顶上。
明白了上面的原理之后,我们可以有两种方式在 Struts2 标签中用 @vs@FOO_PROPERTY 的形式来访问静态变量或静态方法。
1)把常量和静态方法(非它们所在的类)声明在某个根对象中
比如,这里的 IndexAction, 我们在其中声明:
public static final String MY_NAME="Jsrookie come from IndexAction";
在 jsp 中用 <s:property value="@vs@MY_NAME"/> 就能够显示出它的值为: Unmi com from IndexAction。对于静态方法也是类似的。由上图得知,IndexAction 处在 ValueStack 的栈顶,由上往下,即位置为 1 (从零起),所以也可以用 <s:property value="@vs1@MY_NAME"/> 我们也可以来看一下 ValueStack 中是什么样子的,用 <s:debug/> 显示出来是没有变化的,因为静态变量不会显示出来的。
该方法的实际应用,可以把静态变量或静态方法声明在 Action 类中,比如放在 BaseAction 中。或是能否寻找一种更巧妙的方式,在应用程序初始化时把某个 Constants 类中的常量或 Utils 中静态方法用 AOP 或字节码修改的方法插入到 BaseAction 中。这个方法此处不深究了。
2)把常量或静态方法所在类压入到 ValueStack 中直接作为根对象
比如,可以在这里的 IndexAction 的 execute() 方法,或初始方法中加上代码:
ValueStack vs = ActionContext.getContext().getValueStack();
vs.push(new cn.jsrookie.struts2.Constants());
然后在 jsp 中同样是用 <s:property value="@vs@MY_NAME"/> 可以显示出 Constants 的 MY_NAME 静态变量来。现在来看一下新的 ValueStack 的样子,在栈顶多了一个 Constants 对象,这样就可以用 @vs@MY_NAME 或 @vs@foo() 来访问其中的静态变量或静态方法了。你可以使用此代码向 ValueStack 中压入多个实例,比如 vs.push(new cc.unmi.struts2.Utils()),那么你在用 @vs@ 的方式访问时就得知道每个根据对象的位置为,是 @vs@ 还是 @vs1@ 就得自己心里有底了。
实际操作也应该是在你的 BaseAction 的初始化时用把常量类或工具类的实例压到 ValueStack 中。看到这里你可能会有个疑问,我们调用静态方法或常量里推荐用类实例去引用,所以往栈里压入一个 Class 实例更表意,也就是要这么写:
vs.push(cc.unmi.struts.Constans.class);
想法是不错的,然而这样做反而是不行的,你可以看到 ValueStack 中栈顶是一个 java.lang.Class,并且右边是 Class 实例所有的属性,像:
interface false
declaredClasses [Ljava.lang.Class;@1485542
constructors [Ljava.lang.reflect.Constructor;@1d59d3c
componentType null
superclass class java.lang.Object
canonicalName cc.unmi.struts2.Constants
enumConstants null
declaredMethods [Ljava.lang.reflect.Method;@145e5a6
但是却不能用 <s:property value="@vs@MY_NAME"/> 显示出你想要常量来。这其实产生了一个矛盾,通常我们的常量和工具类是不可实例化的,要放在 ValueStack 中的却是它的一个实例,所以要破下常规了。
至于有没有办法直接往 ValueStack 中压入一个相应的 Class 实例,比如借助于泛型的支持,还须进一步细磨一番,不知是否可行。
分享到:
相关推荐
此外,OGNL还能访问类的静态变量和方法。例如,对于类`net.ilkj.ognl.A`,静态变量`a`和静态方法`findA()`可以通过`@net.ilkj.ognl.A@a`和`@net.ilkj.ognl.A@findA()`来调用。 除了OGNL,Struts2还提供了一个丰富的...
### Struts2中OGNL的概念及原理说明 #### 一、OGNL表达式的基本用法与特点 **OGNL**,即**Object Graphic Navigation Language**(对象图导航语言),是Struts2框架中用于处理对象及其属性的强大工具之一。通过...
- 静态属性和方法的访问,包括Action中的静态方法、JDK类的静态方法等,都可以通过OGNL表达式实现。 9. **访问集合**: - OGNL可以方便地访问数组、列表、集合和映射。例如,通过索引访问列表和映射的元素,通过`...
OGNL是Struts2中的默认表达式语言,它提供了简洁的语法来访问和修改对象的属性。例如,`<s:property value="xx" />`标签中的`value="xx"`就是一个OGNL表达式,用于显示对象`xx`的值。 2. OGNL的关键符号: 在OGNL...
在 Struts 2 中,OGNL 是默认的表达式语言,原因是它相对其它表达式语言具有多个优势,例如:支持对象方法调用、支持类静态的方法调用和值访问、支持赋值操作和表达式串联等。 在使用 OGNL 时,经常遇到的问题是 #...
### 精通Struts2中的OGNL表达式 在深入探讨Struts2框架的核心功能时,理解并熟练掌握OGNL(Object-Graph Navigation Language)表达式的应用是至关重要的一步。OGNL是一种强大的表达式语言,它允许开发者通过简洁、...
- 访问类的静态变量和方法:`@完整类名@属性名`或`@完整类名@方法名`。例如,`@net.ilkj.ognl.A@a`访问`A`类的静态变量`a`,`@net.ilkj.ognl.A@findA()`调用静态方法`findA()`。 **Struts2的标签库** Struts2的标签...
这篇概述将深入探讨如何在Struts2中使用OGNL来操作List、Set、Map以及访问方法和静态变量。 1. **OGNL基本概念**:OGNL是基于对象和图形的表达式语言,它允许开发者以简洁的语法动态地访问和修改对象属性。在Struts...
2. **支持类静态的方法调用和值访问**:可以通过特定格式(`@[类全名(包括包路径)]@[方法名|值名]`)访问静态方法或常量,例如 `@java.lang.String@format('foo%s', 'bar')` 或 `@tutorial.MyConstant@APP_NAME`。...
相比EL(Expression Language)表达式,OGNL提供更丰富的功能,如对象方法调用、静态方法调用、值访问以及对集合对象的操作。它的上下文(Context)是一个Map结构,允许存储和访问不同类型的对象,如ActionContext,...
第四章:Struts2中的OGNL.ppt详细探讨了Struts2框架中使用OGNL(Object-Graph Navigation Language,对象图导航语言)的关键概念和技术。OGNL作为一种强大的表达式语言,使得开发者能够方便地访问Action携带的数据,...
OGNL不仅支持属性和方法的访问,还能进行条件判断、循环等复杂逻辑的处理,是Struts2中处理数据流和视图渲染的核心技术之一。 #### 2. OGNL在Struts2中的应用 在Struts2中,OGNL被广泛应用于Action类与视图层之间的...
6. **Struts2的OGNL表达式**:在Freemarker模板中,可以利用Struts2的OGNL(Object-Graph Navigation Language)表达式来访问复杂的对象结构和方法。例如,`${user.address.city}`可以访问User对象的嵌套属性address...
本文主要探讨了Struts2中OGNL的工作机制,包括其基本操作和深入研究的部分。 1. OGNL表达式: OGNL表达式是OGNL的核心,它是一种强大的语法,支持访问对象属性、方法调用、简单的计算、对象创建以及lambda表达式。...
3. `$`:在Struts2中,`$`用于引用非Action上下文中的JavaBean属性或简单变量。例如,`${user.name}`将尝试访问名为`user`的对象的`name`属性。 OGNL还支持更高级的特性,如条件表达式、列表映射、选择操作、以及...
### 在Struts 2中的应用 Struts 2框架利用OGNL作为其默认的表示层表达式语言。以下是一些关键应用场景: - **Action和视图之间的数据绑定**:Action类的属性可以直接通过OGNL表达式在JSP页面中访问,如`${action...
1. **动态属性访问**:除了静态字段和方法,OGNL还可以访问动态属性,如`list[0]`或`map['key']`。 2. **方法调用**:可以直接调用对象的方法,如`object.method()`。 3. **运算符支持**:包括算术运算、比较运算、...
3. **OgnlContext类**:ognl的上下文类,继承自`java.util.Map`,扩展了对变量和方法调用的支持。 4. **ASTNode类**:ognl表达式解析后的抽象基类,每个子类对应一种ognl表达式类型,如`ASTProperty`表示属性访问,...
### Struts2中OGNL表达式的使用与具体实例解析 #### 一、OGNL概述 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取或设置一个对象图中的属性值。它广泛应用于Struts2框架中,用于简化...