OGNL(Object Graphic Navigation Language,对象图导航语言)是一个开源的表达式引擎。通过使用OGNL的表达式语法可以存取Java对象树的任意属性和调用Java对象树的方法等。 Struts2框架就是使用OGNL作为默认的表达式语言。这就是OGNL。
要想把OGNL搞清楚了,比如OGNL到底是从哪里把值取出来的,以及又把值保存在哪里了。这些问题,必须要搞清楚OGNL的原理,你才能回答的到位。说到OGNL的原理,就必须要先说说ActionContext
这个类,ActionContext
表示的是Action的上下文环境,它封装了一个Action运行所需要的环境,比如session、parameters、locale等。如下图所示:
接下来的OGNL的操作都是基于ActionContext而进行的。对于这个ActionContext
来说,每一个请求对应一个Action
,所以说你不用担心什么线程安全的问题了。对于ActionContext
中的SESSION
、APPLICATION
、PARAMETERS
和LOCALE
就不用多说了,我们重点总结的还是VALUE_STACK
。
这个VALUE_STACK
是个什么东西呢?从名字上来看,它应该是个栈,先进后出的属性特点。ValueStack被称为值栈,是对OGNL的扩展,Struts2正式通过ValueStack来使用OGNL进行赋值和取值操作的。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来获取。
说了这么多,现在来看看到底如何真正的使用OGNL。
<s:property value="userName" />
在ValueStack中处于第一位的对象叫栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问ValueStack变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。
ServletContext
的属性,例如:
<s:property value="#application.userName" />
<s:property value="#application['userName']" />
上述代码同调用ServletContext
的getAttribute("userName")
方法的效果是一样的。
HttpSession
的属性,例如:
<s:property value="#session.userName" />
<s:property value="#session['userName']" />
上述代码同调用HttpSession
的getAttribute("userName")
方法的效果是一样的。
HttpServletRequest
的属性,例如:
<s:property value="#request.userName" />
<s:property value="#request['userName']" />
上述代码同调用HttpServletRequest
的getAttribute("userName")
方法的效果是一样的。
<s:property value="#parameters.userName" />
<s:property value="#parameters['userName']" />
上述代码同调用HttpServletRequest
的getParameter("userName")
方法的效果是一样的。
很多时候,我们都会需要一个集合对象,使用OGNL表达式可以直接创建集合对象。
创建List的语法为:
{value1, value2, value3}
创建Map的语法为:
#{key1:value1,key2:value2,key3:value3}
具体的使用示例代码如下:
<!-- 创建一个List -->
<s:set name="varList" value="{'www.google.com','www.facebook.com','www.jellythink.com'}" />
<s:iterator value="#varList" id="n">
<s:property value="n"/><br>
</s:iterator>
<!-- 创建一个Map -->
<s:set name="varMap" value="#{'谷歌':'www.jellythink.com', '脸书':'www.facebook.com', '果冻想':'www.jellythink.com'}" />
<s:iterator value="#varMap" >
<s:property value="key"/>=<s:property value="value"/><br>
</s:iterator>
<s:set .../>
标签用于将某个值放入指定范围,它可以指定以下两个属性:
对于集合,OGNL还提供了以下两个运算符:
in
运算符,判断某个元素是否在集合中not in
运算符,判断某个元素是否不在集合中示例代码如下:
<s:if test="100 in {100,200,300}">
包含
</s:if>
<s:else>
不包含
</s:else>
在开发中,避免不了要访问静态变量和静态方法。为此,OGNL表达式还提供了一种访问静态成员的方式,但Struts2默认是关闭访问静态方法的,只允许通过OGNL表达式访问静态变量。为了让OGNL表达式可以访问静态方法,需要在Struts2配置文件中添加如下配置:
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
为了方便测试,在Action中添加以下几行代码:
public static String strWebSite = "http://www.jellythink.com";
public static String getStrWebSite()
{
return "果冻想 - " + strWebSite;
}
在JSP页面中,我们就可以这样进行访问了:
<s:property value="@com.jellythink.practise.LoginAction@strWebSite" />
<s:property value="@com.jellythink.practise.LoginAction@getStrWebSite()" />
是的,做起来就是这么简单,没什么!
这篇文章就总结到这里了,的确花费了一点时间来总结这篇文章,对于那些不熟悉的地方,都要去写DEMO进行一一验证。好了,下一篇再见~~~
果冻想-一个原创技术文章分享网站。
2016年2月27日 于呼和浩特。
未经允许不得转载:果冻想 » Struts2学习之OGNL表达式