OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它经过简单一致的语法,能够任意存取对象的属性或者调用对象的方法,可以遍历整个对象的结构图,实现对象属性类型的转换等功能。html
Struts 2支持如下几种表达式语言:java
Struts 2默认的表达式语言是OGNL,缘由是它相对其它表达式语言具备下面几大优点:数组
补充:session
(一)对"上下文"概念的理解(百度百科)app
三者之间的关系以下图所示:框架
ActionContext是Action上下文,能够获得request session application。
ValueStack是值栈 存放表单中的值。
Stack Context 栈上下文 也是用来存值的。post
我的见解,action context 是在action中经过actionSupport类来获取到,主要做用是获取request之类的对象,然 后valuestack和stack context都是为了使用OGNL,其中value stack 是stack context的根对象,因此咱们在JSP页面中访问value stack的内容时,是不用加#,而若是是访问stack context的其余对象则要加上#。性能
因为值栈是上下文中的 根对象,所以能够直接访问。那么对于值栈中的对象该如何访问呢?Struts2提供了一个特殊的OGNLPropertyAccessor,它能够自动查找栈内的全部对象(从栈顶到栈底),直接找到一个具备你所查找的属性的对象。也就是说,对于值栈中的任何对象均可以直接访问,而不须要使用“#”。测试
Struts2框架老是把Action实例放在栈顶。由于Action在值栈中,而值栈又是OGNL中的根,因此引用Action的属性能够省略“#”标记,这也是为何咱们在结果页面中能够直接访问Action的属性的缘由。
OGNL的Stack Context里除了包括ValueStack这个根以外,还包括一些命名对象,这些对象没有保存在值栈中,而是保存在ActionContext中,所以访问这些对象须要使用“#”标记。这些命名对象都是Map类型。 this
StackContext“根”对象和普通命名对象的区别在于:
struts2对OGNL上下文的概念又作了进一步扩充,在struts2中,OGNL上下文一般以下所示:
|--request
|
|--application
|
context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|--session
|
|--attr
|
|--parameters
在Struts2中,采用标准命名的上下文(Context)来处理OGNL表达式。处理OGNL的顶级对象是一个Map(也叫context map),而OGNL在这个context中就是一个顶级对象(root)。在用法上,顶级对象的属性访问,是不须要任何标记前缀的。而其它非顶级的对象 访问,须要使用#标记。
Struts2框架把OGNL Context设置为咱们的ActionContext。而且ValueStack做为OGNL的根对象。除value stack以外,Struts2框架还把表明application、session、request这些对象的Map对象也放到 ActionContext中去。(这也就是Struts2建议在Action类中不要直接访问Servlet API的缘由,它能够经过ActionContext对象来部分代替这些(Servlet API)功能 ,以方便对Action类进行测试!)
#符号
#符号的用途通常有三种:
%符号
%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值,这个相似js中的eval,很暴力。
$符号
$符号主要有两个方面的用途:
名字属性获取:<s:property value="user.username"/><br>
地址属性获取:<s:property value="user.address.addr"/><br>
调用值栈中对象的普通方法:<s:property value="user.get()"/><br>
调用Action中的静态方法:<s:property value="@struts.action.LoginAction@get()"/>
调用JDK中的类的静态方法:<s:property value="@Java.lang.Math@floor(44.56)"/><br>
调用JDK中的类的静态方法(同上):<s:property value="@@floor(44.56)"/><br>
调用JDK中的类的静态方法:<s:property value="@java.util.Calendar@getInstance()"/><br>
调用普通类中的静态属性:<s:property value="@struts.vo.Address@TIPS"/><br>
调用普通类的构造方法:<s:property value="new struts.vo.Student('李晓红' , '美女' , 3 , 25).username"/>
获取List:<s:property value="testList"/><br>
获取List中的某一个元素(可使用相似于数组中的下标获取List中的内容):
<s:property value="testList[0]"/><br>
获取Set:<s:property value="testSet"/><br>
获取Set中的某一个元素(Set因为没有顺序,因此不能使用下标获取数据):
<s:property value="testSet[0]"/><br> ×
获取Map:<s:property value="testMap"/><br>
获取Map中全部的键:<s:property value="testMap.keys"/><br>
获取Map中全部的值:<s:property value="testMap.values"/><br>
获取Map中的某一个元素(可使用相似于数组中的下标获取List中的内容):
<s:property value="testMap['m1']"/><br>
获取List的大小:<s:property value="testSet.size"/><br>
利用选择获取List中成绩及格的对象:<s:property value="stus.{?#this.grade>=60}"/><br>
利用选择获取List中成绩及格的对象的username:
<s:property value="stus.{?#this.grade>=60}.{username}"/><br>
利用选择获取List中成绩及格的第一个对象的username:
<s:property value="stus.{?#this.grade>=60}.{username}[0]"/><br>
利用选择获取List中成绩及格的第一个对象的username:
<s:property value="stus.{^#this.grade>=60}.{username}"/><br>
利用选择获取List中成绩及格的最后一个对象的username:
<s:property value="stus.{$#this.grade>=60}.{username}"/><br>
利用选择获取List中成绩及格的第一个对象而后求大小:
<s:property value="stus.{^#this.grade>=600}.{username}.size"/><br>
OGNL可以引用集合的一些特殊的属性,这些属性并非JavaBeans模式,例如size(),length()等等. 当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性.
使用Lambda表达式计算阶乘:
<s:property value="#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)"/><br>
获取Paraments对象的属性:<s:property value="#parameters.username"/>
用%{}能够取出存在值堆栈中的Action对象,直接调用它的方法.
例如你的Action若是继承了ActionSupport .那么在页面标签中,用%{getText('key')}的方式能够拿出国际化信息.
OGNL中$的使用
“$”有两个主要的用途
用于在国际化资源文件中,引用OGNL表达式
在Struts 2配置文件中,引用OGNL表达式
ValueStack对象。这个对象贯穿整个Action的生命周期(每一个Action类的对象实例会拥有一个ValueStack对象)。当Struts 2接收到一个.action的请求后,会先创建Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象至关于一个栈)。
在Action中得到ValueStack对象:ActionContext.getContext().getValueStack()
Top语法:使用Top获取值栈中的第二个对象:<s:property value="[1].top.对象"/>
N语法:使用N获取值栈中的第二个对象:<s:property value="[1].对象"/>
@语法:调用action中的静态方法:<s:property value="@vs1@静态方法"/> vs:值栈 1:表示第一个。