struts2中OGNL的具体用法实例源码介绍



struts2中OGNL的具体用法实例源码介绍。

1.“#”用于声明OGNL表达式,有3种用途:
一.能够访问OGNL的上下文和ActionContext资源,相当于ActionContext.getContext();
1.#parameters,代表request.getParameterValues(“id”);返回String[]类型,一般使用#parameters.id[i];
2.#request,代表request.getAttribute(“account”);相当于#request.account;
3.#session,代表session.getAttribute(“account”);相当于#session.account;
4.#application,代表application.getAttribute(“account”);相当于#application.account;
5.#attr,代表request,session,application里面所有的属性,#attr.account相当于EL表达式中的${account},依次查看request,session,application,找到为止.

二.用于过滤或筛选集合,例如:books.{?#this.price<20};

三.构造Map,如#{‘foo1’:‘bar1’,‘foo2’:‘bar2’};

例子:
maganize是javabean类,里面有属性{String name,int price};
Action中有List<maganize> maganizeList = new ArrayList(){····};
<s:property value=“maganizeList.{?#this.price>18}.size()” />
<s:property value=“maganizeList.{?#this.name.contains(‘XXX’)}.size()” />
<s:iterator value=“maganizeList.{?#this.price>18}”/>
<s:property value=“name”/><s:property value=“price”/>
</s:iterator>

2.“%”显示声明OGNL表达式:用于某些标签中既能够接受字符,又能够接受OGNL表达式:
例如:<s:label label=”#request.account” /> 会直接显示:#request.account出来
如果是:<s:label label=”%{#request.account}” />就会是显示出account的值

3.“$”使用在配置文件中:AAA.xml都行
例如在struts.xml中:
<action name=”" >
<result>·······?id=${id}</result>
</action>

额外的增加一点<s:if>的用法:
<s:if test=”#parameters.name[0]==‘yao’”>···</s:if>
<s:if test=”name==‘yao’”>···</s:if> 此处的name必须是action中的一个属性…

http://blog.sina.com.cn/s/blog_6ced643701010u57.html

struts2 OGNL # % $
2010-08-31 19:52:05
标签:struts2 OGNL # % $ 休闲 职场
下午对这个地方一直感觉很模糊……然后“决心”查一查,查了之后还是有效果的!嘿嘿……野猪,加油!野猪记住!你是一只野猪,现在是,将来也是!要学会独立!嘿嘿……说正题吧……
一、”#”的用法
1、 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameter(“id”)
request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute(“userName”)
session 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute(“userName”)
application 包含当前应用的ServletContext的属性(attribute)的Map #application.userName相当于application.getAttribute(“userName”)
attr 用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
2、用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3、构造Map,如#{‘foo1′:’bar1′, ‘foo2′:’bar2′}。
二、”%”的用法
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<h3>%的用途</h3>
<p><s:url value=”#foobar['foo1']” /></p>
<p><s:url value=”%{#foobar['foo1']}” /></p>
三、”$”的用法
1、用于在国际化资源文件中,引用OGNL表达式
2、在Struts 2配置文件中,引用OGNL表达式
例如:
<action name=”AddPhoto” class=”addPhoto”>
<interceptor-ref name=”fileUploadStack” />
<result type=”redirect”>ListPhotos.action? albumId=${albumId}</result>
</action>
struts2中的OGNL上下文
struts2对OGNL上下文的概念又做了进一步扩充,在struts2中,OGNL上下文通常如下所示:
|–request
|
|–application
|
context map—|–OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|–session
|
|–attr
|
|–parameters
我们可以使用”#requet”访问HttpServletRequest对象, “#session”访问HttpSession对象,但请注意”根对象”是什么?是ValueStack!
那么ValueStack是什么?值栈。也就是一组对象的堆栈。也就是说,在struts2中,根对象不是我们通常的一个对象,而是一组对象。我们可以 push新的对象到值栈中,也可以弹出值栈的栈顶对象。如上图所示,假设我们将user对象push到值栈中,那么如下的表达式将与之前我们见过的表达式一样,具有相同的结果:
Java代码
name // 取用户的姓名
age // 取用户年龄
birthday // 取用户生日
customer.name // 取用户所属客户的名称
#request.parameters // 取请求参数
也就是说,我们使用name这个表达式的时候,ONGL会取”根对象”的name属性,但现在根对象是ValueStack!那么访问 ValueStack的name属性意味着什么呢?这意味着: ValueStack会先查看栈顶元素是否有name属性,如果有就返回该属性值,否则取出栈顶下的元素,继续查看,直到栈底为止。
关于ValueStack
Struts2的Action类通过属性可以或得所有相关的值,如请求参数、action配置参数、向其他Action传递属性值(通过Chain结果)等等。
要获得这些参数值,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在Struts2调用Action类的Action方法之前,就会为相应的Action属性赋值,要完成这个功能,有很大程度上,Struts2要依赖ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。处理完上述工作后,Struts2就会调用拦截器链中的拦截器,当调用完所有的拦截器后,最后会调用Action类的Action方法,在调用Action方法之前,会将ValueStack对象顶层节点中的属性值赋给Action类中相应的属性,注意,在这里就给我们呆了很大的灵活性。也就是说,在Struts2调用拦截器的过程中,可以改变ValueStack对象中属性的值,当改变某个属性之后,Action类的相应属性值就会变成在拦截器中最后改变该属性的这个值。
从上面的描述很容易知道,在Struts2的Action类可以获得与属性同名的参数值就是通过不同的拦截器来处理的,如获得请求参数的拦截器是params,获得Action的配置参数的拦截器是staticParams等,在这些拦截器内部读取相应的值,并更新ValueStack对象顶层节点的相应属性的值。而ValueStack对象就像一个传送带,将属性的值从一个拦截器传到了另一个拦截器(当然,在这期间,属性值可能改变),最后会传到Action对象,并将ValueStack对象中的属性的值的终值赋给Action类的相应属性。
1、值栈(ValueStack)
Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlContext),并将值栈设为OGNL的根对象。
我们知道,OGNL上下文中的根对象可以直接访问,不需要使用任何特殊的“标记”,而引用上下文中的其他对象则需要使用“#”来标记。由于值栈是 上下文中的根对象,因此可以直接访问。那么对于值栈中的对象该如何访问呢?Struts2提供了一个特殊的OGNLPropertyAccessor,它 可以自动查找栈内的所有对象(从栈顶到栈底),直接找到一个具有你所查找的属性的对象。也就是说,对于值栈中的任何对象都可以直接访问,而不需要使用 “#”。
假设值栈中有两个对象:student和employee,两个对象都有name属性,student有学号属性number,而 employee有薪水属性salary。employee先入栈,student后入栈,位于栈顶,那么对于表达式name,访问的就是student 的name属性,因为student对象位于栈顶;表达式salary,访问的就是employee的salary属性。正如你所见,访问值栈中的对象属 性或方法,无须指明对象,也不用“#”,就好像值栈中的对象都是OGNL上下文中的根对象一样。这就是Struts2在OGNL基础上做出的改进。
2、[N]语法
如上所述,如果想要访问employee的name属性,应该如何写表达式呢?我们可以使用[N].xxx(N是从0开始的整数)这样的语法来指定从哪一个位置开始向下查找对象的属性,表达式[1].name访问的就是employee对象的name属性。
在使用[N].xxx语法时,要注意位置序号的含义,它并不是表示“获取栈中索引为N的对象”,而是截取从位置N开始的部分栈。
3、top关键字
top用于获取栈顶的对象,结合[N].xxx语法,我们就可以获取栈中任意位置的对象。
如:[0].top,[1].top等
4、访问静态成员
除了使用标准的OGNL表达式访问静态字段和静态方法外,Struts2还允许你不指定完整的类名,而是通过“vs”前缀来调用保存在栈中的静态字段和静态方法。
@vs@FOO_PROPERTY
@vs@someMethod()
@vs1@someMethod()
vs表示ValueStack,如果只有vs,那么将使用栈顶对象的类;如果在vs后面跟上一个数字,那么将使用栈中指定位置处的对象类。
5、值栈中的Action实例
Struts2框架总是把Action实例放在栈顶。因为Action在值栈中,而值栈又是OGNL中的根,所以引用Action的属性可以省略“#”标记,这也是为什么我们在结果页面中可以直接访问Action的属性的原因。
6、Struts2中的命名对象
Struts2还提供了一些命名对象,这些对象没有保存在值栈中,而是保存在ActionContext中,因此访问这些对象需要使用“#”标记。这些命名对象都是Map类型。
parameters
用于访问请求参数。如:#parameters['id']或#parameters.id,相当于调用了HttpServletRequest对象的getParameter()方法。
注意,parameters本质上是一个使用HttpServletRequest对象中的请求参数构造的Map对象,一量对象被创建(在调用Action实例之前就已经创建好了),它和HttpServletRequest对象就没有了任何关系。
request
用于访问请求属性。如:#request['user']或#request.user,相当于调用了HttpServletRequest对象的getAttribute()方法。
session
用于访问session属性。如:#session['user']或#session.user,相当于调用了HttpSession对象的getAttribute()方法。
application
用于访问application属性。如:#application['user']或#application.user,相当于调用了ServletContext的getAttribute()方法。
attr
如果PageContext可用,则访问PageContext,否则依次搜索request、session和application对象。

这里面野猪进行了综合……野猪看了之后明白了许多~呵呵……

http://yin123.blog.51cto.com/882581/385721

Struts2中的OGNL表达式

浅析值栈
ValueStack对象相当于一个,它贯穿整个Action的生命周期,每个Action类的对象实例都会拥有一个ValueStack对象
当Struts2接收到一个*.action请求后,并不是直接调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点
值栈也位于内存中,它也是和parameters、request、session、application、attr对象放在一起的
值栈属于ONGLContext里面的根对象。也就是说它位于整个内存中最最重要的地方,所以叫根对象
根对象和另外五个对象是有区别的,根对象可以省写#号,比如<s:property value=”user.username”/>
值栈的生命周期与request请求相关,每次请求产生一个值栈。默认所有的Action会被自动放到值栈里

 

服务器跳转时共用值栈
假设从一个Action11通过服务器跳转到Action22的话,就意味着这两个Action是共享一个值栈的,因为一次请求只使用一个值栈
这时内存中情况是这样的:首先接收到Action11请求后,会产生一个值栈,在栈顶存放Action11对象以及它所有的属性
然后经过服务器跳转到Action22,这时就会把Action22对象压入值栈的栈顶位置,此时Action11对象以及它的所有属性就位于栈底了

 

取值过程
栈的特征是后进先出。于是首先到栈顶的对象里查找是否存在这个属性,如果栈顶的Action22对象中不存在这个属性的话
它就会继续向下寻找直至栈底对象,一直查找是否存在这个属性
如果最后找到该属性的话,那么就会在JSP页面中通过<s:property value=”username”/>输出属性值
如果在Action22和Action11都有一个同名的同类型的username属性的话,那么将输出Action22中的属性值
因为它是先从栈顶开始寻找属性的,值栈的特征就是后进先出,但有个前提:请求过程是通过服务器跳转的

 

三个语法
假设此时想要获取Action11中的username属性的话,就可以使用值栈的Top语法或者N语法
使用Top语法获取值栈中的第二个对象的属性:<s:property value=”[1].top.username”/>
使用N语法获取值栈中的第二个对象的属性:<s:property value=”[1].username”/>
另外值栈还有一个@语法,例如使用@语法调用Action中的静态方法:<s:property value=”@vs@getVOMethod()”/>
@vs@get()等价于@vs1@getVOMethod(),指的是栈顶对象的静态getVOMethod()方法
同理@vs2@getVOMethod()就是取值栈中第二个对象的静态getVOMethod()方法

 

客户端跳转时使用各自的值栈
假如中间某一个步骤中出现了客户端跳转的话,那么两个Action所使用的就是两个不同的值栈了
所以在Action22中就不能再使用Action11中的属性了,在最后跳转到的JSP页面中也就无法获取Action11的属性了
也即从Action22跳转到JSP页面时使用的是redirect的话,那么最后值栈中是没有任何的Action对象的
这个时候我们可以通过链接传参,比如<result type=”redirect”>test.jsp?netname=${username}</result>
意思就是取出Action22中的username属性作为参数,通过浏览器地址栏传递到JSP页面中
然后使用OGNL中的#号获取Paraments对象的属性,即<s:property value=”#parameters.netname”/>就可以取到值了
辅助参考:http://blog.csdn.net/jadyer/archive/2010/09/16/5887509.aspx

 

手工向值栈中压入对象
正常情况下值栈保存的是Action对象,而我们也可以直接往值栈中添加其它对象,这时可以在Action中添加如下代码
向值栈中添加对象:ActionContext.getContext.getValueStack().push(new Student(“沈浪”,22));
而且我们手工往值栈中添加的Student对象会位于栈顶。这是因为Struts2会首先初始化Action,然后才能调用它的方法
初始化Action的时候,便把Action放到值栈中了,然后在执行它的execute()方法时,就又往值栈中添加了Student对象

 

浅析OGNL
OGNL是Object-Graph Navigation Language的缩写,是一种功能强大的表达式语言
通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能
OGNL用得最多的地方就是和Struts2的标签绑定,也可以在配置文件中通过${}使用OGNL表达式

 

OGNL中$号的使用
1..在国际化资源文件中,引用OGNL表达式
2..在struts.xml文件中,引用OGNL表达式

 

OGNL中%号的使用
1..使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法
2..如果Action继承了ActionSupport,那么在页面标签中可以使用%{getText(‘key’)}获取国际化信息
辅助参考:http://blog.csdn.net/jadyer/archive/2010/09/16/5887545.aspx

 

OGNL中#号的使用
OGNL中的#号可以取出堆栈上下文中存放的对象

名称 作用 例子
attr 用于按request>>session>>application顺序访问其属性 #attr.userName相当于按顺序从三个范围读取userName属性直到找到为止
request 包含当前HttpServletRequest的属性的Map #request.userName相当于request.getAttribute(“userName”)
session 包含当前HttpSession的属性的Map #session.userName相当于session.getAttribute(“userName”)
application 包含当前应用的ServletContext的属性的Map #application.userName相当于application.getAttribute(“userName”)
parameters 包含当前HTTP请求参数的Map #parameters.id[0]相当于request.getParameter(“id”)

 

 

获取Action中的属性值或者Action中的对象的某某属性值
利用<s:property/>标签可以直接获取Action中的引用类型user里面的username属性
同样可以通过user.address.addr获取user中引用类型address中的addr属性的值
像这种一层一层往下传递的访问方式,即所谓的导航,也就是一步步的往下调用

 

调用Action的对象里面的普通方法
默认的会把Action放到值栈里面,而值栈在访问的时候,并不需要值栈的名字
当我们调用<s:property value=”user.getVOMethod()”/>的时候
它会自动到值栈里面查找Action对象里面有没有user对象,然后它就发现有user
然后它就再找user里面有没有getVOMethod()方法,然后它发现有,于是调用getVOMethod()
实际上调用User中的getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的
都是到值栈里面查找,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法


 

调用Action中的静态方法
同样我们也可以在JSP页面中写一个OGNL表达式调用Action中的静态方法
调用Action中的静态方法时,与调用user对象的getVOMethod()方法的过程,是截然不同的
此时value的写法是固定的,以@开头,后面跟上具体的包名,然后@加上静态方法
比如<s:property value=”@com.jadyer.action.LoginAction@getStatic()”/>
另外user对象是LoginAction中的一个属性,这个属性会自动的放到值栈里面
而值栈调用的时候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了

 

调用JDK类中的静态方法
可以使用<s:property value=”@@floor(46.58)”/>输出floor()的执行结果
这就意味着如果不在@@中指定类的话,默认的就表示java.lang.Math类
当前大多数情况下,我们都不会省略这个类,都会写全了的,然后在后面加上静态方法

 

集合的伪属性
OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size()、length()
当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性
比如获取List的大小:<s:property value=”testList.size”/>
List的伪属性:size、isEmpty、iterator
Set的伪属性:size、isEmpty、iterator
Map的伪属性:size、isEmpty、keys、values
Iterator的伪属性:next、hasNext
Enumeration伪属性:next、hasNext、nextElement、hasMoreElements

 

获取集合中元素的实质就是调用它的toString()方法
它还可以直接获取集合中的元素,事实上是在调用集合的toString()方法
所以我们可以根据实际情况通过重写集合的toString()方法来实现个性化输出
甚至它还可以像访问数组那样,直接testList[2]获取集合中的元素
但这种方法只适用于List,不适用于Map。因为Map的索引是key,不是数值
另外,由于HashSet中的元素是没有顺序的,所以也不能用下标获取单个元素

 

Lambda表达式
补充一下:使用Lambda表达式可以在OGNL中书写递归式子,在帮助中对它有很详细的说明
打开帮助中的//struts-2.0.14-all//struts-2.0.14//docs//index.html页面
在左侧的Documentation下面点击Guides链接,然后在这个页面中点击OGNL
最后跳转到//struts-2.0.14-all//struts-2.0.14//docs//docs//ognl.html
将这个页面右侧的下拉条拖放到最下面,就会看到它的说明了,它举的例子如下所示
<s:property value=”#fib=:[#this==0?0:#this==1?1:#fib(#this-2)+#fib(#this-1)],#fib(11)”/>
Lambda表达式的语法是:[...],中括号前面有一个冒号,所有东西都在中括号里面写
也就是说我们只要看到一个冒号跟着一个中括号,就表示这里使用的是Lambda表达式
#this指的是表达式的参数
所以这个例子可以这样理解:先判断这个参数是否等于零,如果等于零,那么它的值最后就是零
如果参数不等于零,就再判断它是否等于壹。如果参数等于壹,那么它的值最后就是壹
如果参数不等于壹,就继续调用#fib。注意这里已经用中括号将整体的值赋给了fib
实际上很少能够用得到Lambda表达式

 

利用投影获取属性
利用投影获取List中对象的username属性时,其中{}表示的是一个集合
stus.{username}就表示将suts中所有的username属性取出组成一个新的列表

 

利用选择获取属性
OGNL表达式是很灵活的,可以同时使用选择技术投影技术获取属性
使用选择技术时,#this代表当前元素,问号?是把所有满足条件的元素都取出来
上箭头^是开始的意思,所以stus.{^#this.grade>=60}.{username}输出的是[张三]
注意,此时输出文本中包含中括号,这表示它是一个列表
stus.{?#this.grade>=60}.{username}[0]输出的是张三,是字符串,二者是不同的
美元符号$是结束的意思,所以stus.{$#this.grade>=60}.{username}输出的是[王五]
这三个符合:问号、上箭头、美元符所返回的都是List

 

补充
1..当OGNL取不到值的时候,它不会报错,而是什么都不显示
2..<s:property value=”[0]“/>返回的是ValueStack中从上至下的所有的Object
<s:property value=”[1]“/>返回的是ValueStack中从上至下的第二个Object
3..<s:property value=”[0].username”/>返回的是成员变量username的值
假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量
那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action呢
答案是在struts.xml中配置的是从一个Action通过<result type=”chain”>跳转到另一个Action
4..<constant name=”struts.ognl.allowStaticMethodAccess” value=”true”/>
Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccess为true之后
才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置,即可直接访问


下面是OGNL测试的工程代码,这是一个Struts2.0.11应用

首先是web.xml文件

 

  1. <?xmlversion=”1.0″encoding=”UTF-8″?>
  2. <web-appversion=”2.5″
  3. xmlns=”http://java.sun.com/xml/ns/javaee”
  4. xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  5. xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee
  6. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”>
  7. <filter>
  8. <filter-name>struts2</filter-name>
  9. <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  10. </filter>
  11. <filter-mapping>
  12. <filter-name>struts2</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>
  15. <welcome-file-list>
  16. <welcome-file>login.jsp</welcome-file>
  17. </welcome-file-list>
  18. </web-app>

 

然后是用于输入用户名和密码等信息的测试页面login.jsp

 

  1. <%@pagelanguage=”java”pageEncoding=”UTF-8″%>
  2. <h1>这是测试OGNL使用的登录页面</h1>
  3. <h3><fontcolor=”red”>提示:</font>程序设定的用户名和密码各为<fontcolor=”blue”><strong>admin</strong></font>和<fontcolor=”blue”><strong>jadyer</strong></font></h3>
  4. <h3><fontcolor=”red”>注意:</font>用户名和密码不正确时将停留在页面不动</h3>
  5. <formaction=”<%=request.getContextPath()%>/login.action”method=”POST”>
  6. <%–这里user.username匹配的是LoginAction中的引用类型user里面的username属性–%>
  7. <%–查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式–%>
  8. 姓名:<inputtype=”text”name=”user.username”><br>
  9. 密码:<inputtype=”text”name=”user.password”><br>
  10. 地址:<inputtype=”text”name=”user.address.addr”><br>
  11. <inputtype=”submit”value=”测试OGNL的输出”>
  12. </form>

 

然后是用于显示OGNL处理结果的loginSuc.jsp页面

 

  1. <%@pagelanguage=”java”pageEncoding=”UTF-8″%>
  2. <%@taglibprefix=”s”uri=”/struts-tags”%>
  3. <h1>这是使用OGNL输出的结果页面</h1>
  4. <tableborder=”9″>
  5. <tr>
  6. <tdalign=”right”>获取姓名属性:</td>
  7. <tdalign=”left”><s:propertyvalue=”user.username”/></td>
  8. <%–另外还有两种写法也是可以正常输出值栈中对象的普通属性的–%>
  9. <%–<s:propertyvalue=”user['username']“/>–%>
  10. <%–<s:propertyvalue=”user[/"username/"]“/>–%>
  11. <%–但是如果写成下面这种形式的话,就什么都不会输出了–%>
  12. <%–<s:propertyvalue=”user[username]“/>–%>
  13. </tr>
  14. <tr>
  15. <tdalign=”right”>获取地址属性:</td>
  16. <tdalign=”left”><s:propertyvalue=”user.address.addr”/></td>
  17. </tr>
  18. <tr>
  19. <tdalign=”right”>调用值栈中的对象的普通方法:</td>
  20. <tdalign=”left”><s:propertyvalue=”user.getVOMethod()”/></td>
  21. </tr>
  22. <tr>
  23. <tdalign=”right”>调用值栈中Action的普通方法:</td>
  24. <tdalign=”left”><s:propertyvalue=”getCommon()”/></td>
  25. </tr>
  26. </table>
  27. <hr/>
  28. <tableborder=”9″>
  29. <tr>
  30. <tdalign=”right”>获取普通类的静态属性:</td>
  31. <tdalign=”left”><s:propertyvalue=”@com.jadyer.vo.Address@TIPS”/></td>
  32. </tr>
  33. <tr>
  34. <tdalign=”right”>访问普通类的构造方法:</td>
  35. <tdalign=”left”><s:propertyvalue=”newcom.jadyer.vo.Student(‘张小三’,22).username”/></td>
  36. </tr>
  37. <tr>
  38. <tdalign=”right”>调用Action中的静态方法:</td>
  39. <tdalign=”left”><s:propertyvalue=”@com.jadyer.action.LoginAction@getStatic()”/></td>
  40. </tr>
  41. <tr>
  42. <tdalign=”right”>调用JDK中的类的静态方法:</td>
  43. <tdalign=”left”><s:propertyvalue=”@java.util.Calendar@getInstance().time”/></td>
  44. </tr>
  45. <tr>
  46. <tdalign=”right”>调用JDK中的类的静态方法:</td>
  47. <tdalign=”left”><s:propertyvalue=”@java.lang.Math@floor(46.58)”/></td>
  48. </tr>
  49. <tr>
  50. <tdalign=”right”>调用JDK中的类的静态方法:</td>
  51. <tdalign=”left”><s:propertyvalue=”@@floor(46.58)”/></td>
  52. </tr>
  53. </table>
  54. <hr/>
  55. <tableborder=”9″>
  56. <tr>
  57. <tdalign=”right”>获取List中的所有元素:</td>
  58. <tdalign=”left”><s:propertyvalue=”testList”/></td>
  59. </tr>
  60. <tr>
  61. <tdalign=”right”>获取Set中的所有元素:</td>
  62. <tdalign=”left”><s:propertyvalue=”testSet”/></td>
  63. </tr>
  64. <tr>
  65. <tdalign=”right”>获取Map中的所有元素:</td>
  66. <tdalign=”left”><s:propertyvalue=”testMap”/></td>
  67. </tr>
  68. <tr>
  69. <tdalign=”right”>获取Map中的某个元素:</td>
  70. <tdalign=”left”><s:propertyvalue=”testMap['m22']“/></td>
  71. <%–另外还有两种写法也是可以正常获取Map中的某个具体元素的–%>
  72. <%–<s:propertyvalue=”testMap.m22″/>–%>
  73. <%–<s:propertyvalue=”testMap[/"m22/"]“/>–%>
  74. </tr>
  75. <tr>
  76. <tdalign=”right”>获取Set中的某个元素:</td>
  77. <%–由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到–%>
  78. <tdalign=”left”><s:propertyvalue=”testSet[2]“/></td>
  79. </tr>
  80. <tr>
  81. <tdalign=”right”>获取List中的某个元素:</td>
  82. <tdalign=”left”><s:propertyvalue=”testList[2]“/></td>
  83. </tr>
  84. </table>
  85. <hr/>
  86. <tableborder=”9″>
  87. <tr>
  88. <tdalign=”right”>获取List的大小:</td>
  89. <tdalign=”left”><s:propertyvalue=”testList.size”/></td>
  90. </tr>
  91. <tr>
  92. <tdalign=”right”>获取Set的大小:</td>
  93. <tdalign=”left”><s:propertyvalue=”testSet.size”/></td>
  94. </tr>
  95. <tr>
  96. <tdalign=”right”>获取Map的大小:</td>
  97. <tdalign=”left”><s:propertyvalue=”testMap.size”/></td>
  98. </tr>
  99. <tr>
  100. <tdalign=”right”>获取Map中所有的键:</td>
  101. <tdalign=”left”><s:propertyvalue=”testMap.keys”/></td>
  102. </tr>
  103. <tr>
  104. <tdalign=”right”>获取Map中所有的值:</td>
  105. <tdalign=”left”><s:propertyvalue=”testMap.values”/></td>
  106. </tr>
  107. <tr>
  108. <tdalign=”right”>Lambda计算4的阶乘:</td>
  109. <tdalign=”left”><s:propertyvalue=”#f=:[#this==1?1:#this*#f(#this-1)],#f(4)”/></td>
  110. </tr>
  111. </table>
  112. <hr/>
  113. <tableborder=”9″>
  114. <tr>
  115. <tdalign=”right”>获取List中的所有对象:</td>
  116. <tdalign=”left”><s:propertyvalue=”stus”/></td>
  117. </tr>
  118. <tr>
  119. <tdalign=”right”>利用投影获取List中对象的名字:</td>
  120. <tdalign=”left”><s:propertyvalue=”stus.{username}”/></td>
  121. </tr>
  122. <tr>
  123. <tdalign=”right”>利用投影获取List中第二个对象的名字:</td>
  124. <%–使用<s:propertyvalue=”stus[1].{username}”/>获取到的值为:[李四]–%>
  125. <%–二者的区别在于:后者比前者多了一个中括号–%>
  126. <tdalign=”left”>
  127. <s:propertyvalue=”stus.{username}[1]“/>
  128. <s:propertyvalue=”stus[1].{username}”/>
  129. </td>
  130. </tr>
  131. <tr>
  132. <tdalign=”right”>利用选择获取List中成绩及格的所有对象:</td>
  133. <tdalign=”left”><s:propertyvalue=”stus.{?#this.grade>=60}”/></td>
  134. </tr>
  135. <tr>
  136. <tdalign=”right”>利用选择获取List中成绩及格的第一个对象:</td>
  137. <tdalign=”left”><s:propertyvalue=”stus.{^#this.grade>=60}”/></td>
  138. </tr>
  139. <tr>
  140. <tdalign=”right”>利用选择获取List中成绩及格的最后一个对象:</td>
  141. <tdalign=”left”><s:propertyvalue=”stus.{$#this.grade>=60}”/></td>
  142. </tr>
  143. </table>
  144. <hr/>
  145. <tableborder=”9″>
  146. <tr>
  147. <tdalign=”right”>利用选择获取List中成绩及格的所有对象的名字:</td>
  148. <tdalign=”left”><s:propertyvalue=”stus.{?#this.grade>=60}.{username}”/></td>
  149. </tr>
  150. <tr>
  151. <tdalign=”right”>利用选择获取List中成绩及格的第二个对象的名字:</td>
  152. <tdalign=”left”><s:propertyvalue=”stus.{?#this.grade>=60}.{username}[1]“/></td>
  153. </tr>
  154. <tr>
  155. <tdalign=”right”>利用选择获取List中成绩及格的第一个对象的名字:</td>
  156. <tdalign=”left”><s:propertyvalue=”stus.{^#this.grade>=60}.{username}”/></td>
  157. </tr>
  158. <tr>
  159. <tdalign=”right”>利用选择获取List中成绩及格的最后一个对象的名字:</td>
  160. <tdalign=”left”><s:propertyvalue=”stus.{$#this.grade>=60}.{username}”/></td>
  161. </tr>
  162. <tr>
  163. <tdalign=”right”>利用选择获取List中成绩及格的第一个对象然后求大小:</td>
  164. <tdalign=”left”><s:propertyvalue=”stus.{^#this.grade>=60}.{username}.size”/></td>
  165. </tr>
  166. </table>
  167. <hr/>
  168. <tableborder=”9″>
  169. <tr>
  170. <tdalign=”right”>利用OGNL中的#号获取attr中的属性:</td>
  171. <tdalign=”left”><s:propertyvalue=”#attr.BB”/></td>
  172. </tr>
  173. <tr>
  174. <tdalign=”right”>利用OGNL中的#号获取request范围中的属性:</td>
  175. <tdalign=”left”><s:propertyvalue=”#request.req”/></td>
  176. </tr>
  177. <tr>
  178. <tdalign=”right”>利用OGNL中的#号获取session范围中的属性:</td>
  179. <tdalign=”left”><s:propertyvalue=”#session.ses”/></td>
  180. </tr>
  181. <tr>
  182. <tdalign=”right”>利用OGNL中的#号获取Paraments对象的属性:</td>
  183. <tdalign=”left”><s:propertyvalue=”#parameters.netname”/></td>
  184. </tr>
  185. <tr>
  186. <tdalign=”right”>使用&#60;&#37;=request.getParameter&#40;”"&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td>
  187. <tdalign=”left”>
  188. ${param.netname}
  189. <%=request.getParameter(“netname”)%>
  190. </td>
  191. </tr>
  192. <tr>
  193. <tdalign=”right”>查看值栈中的信息:</td>
  194. <tdalign=”left”><s:debug/></td>
  195. </tr>
  196. </table>

 

然后是struts.xml文件

 

  1. <?xmlversion=”1.0″encoding=”UTF-8″?>
  2. <!DOCTYPEstrutsPUBLIC
  3. “-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN”
  4. “http://struts.apache.org/dtds/struts-2.0.dtd”>
  5. <struts>
  6. <packagename=”ognl”extends=”struts-default”>
  7. <actionname=”login”class=”com.jadyer.action.LoginAction”>
  8. <resultname=”input”>/login.jsp</result>
  9. <resultname=”success”>/loginSuc.jsp?netname=hongyu</result>
  10. <!–
  11. <resultname=”success”type=”redirect”>/loginSuc.jsp?netname=hongyu</result>
  12. <resultname=”success”type=”redirect”>/loginSuc.jsp?netname=${user.username}</result>
  13. –>
  14. </action>
  15. </package>
  16. </struts>

 

接着是用到的三个VO类

 

  1. packagecom.jadyer.vo;
  2. publicclassUser{
  3. privateStringusername;
  4. privateStringpassword;
  5. privateAddressaddress;
  6. /*三个属性的setter和getter略*/
  7. publicStringgetVOMethod(){
  8. return”这是User类中的一个普通方法”;
  9. }
  10. }
  11. packagecom.jadyer.vo;
  12. publicclassAddress{
  13. //如果将TIPS设为private的话,loginSuc.jsp中就无法获取它的属性值了
  14. //事实上将一个静态的final属性设为private是毫无意义的
  15. //因为既然设置成了静态,那么就是供他人调用的,如果再设成private的话,别的地方根本就无法调用了
  16. //即使OGNL再怎么强大,它也不可能违反Java的规则,所以不要将静态的属性设为私有
  17. publicstaticfinalStringTIPS=”玄玉加油!!”;
  18. //addr属性的setter和getter略
  19. privateStringaddr;
  20. }
  21. packagecom.jadyer.vo;
  22. publicclassStudent{
  23. privateStringusername;
  24. privateintgrade;
  25. /*两个属性的setter和getter略*/
  26. //只要是重写一个类的构造方法,就必须要为这个类保留空的构造方法
  27. //因为框架默认的都会去调用无参的空的构造方法
  28. publicStudent(){};
  29. publicStudent(Stringusername,intgrade){
  30. this.username=username;
  31. this.grade=grade;
  32. }
  33. @Override
  34. publicStringtoString(){
  35. //如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】
  36. return”{学生姓名:”+username+”,成绩:”+grade+”}”;
  37. }
  38. }

 

最后是用来提供OGNL测试的数据的LoginAction.java

 

  1. packagecom.jadyer.action;
  2. importjava.util.ArrayList;
  3. importjava.util.HashMap;
  4. importjava.util.HashSet;
  5. importjava.util.List;
  6. importjava.util.Map;
  7. importjava.util.Set;
  8. importorg.apache.struts2.interceptor.RequestAware;
  9. importorg.apache.struts2.interceptor.SessionAware;
  10. importcom.jadyer.vo.Student;
  11. importcom.jadyer.vo.User;
  12. importcom.opensymphony.xwork2.ActionSupport;
  13. @SuppressWarnings({“serial”,”unchecked”})
  14. publicclassLoginActionextendsActionSupportimplementsRequestAware,SessionAware{
  15. privateUseruser;
  16. privateListtestList=newArrayList();
  17. privateSettestSet=newHashSet();
  18. privateMaptestMap=newHashMap();
  19. privateListstus=newArrayList();
  20. /*以上五个属性的setter和getter略*/
  21. privateMaprequest;
  22. privateMapsession;
  23. publicvoidsetRequest(Maprequest){
  24. this.request=request;
  25. }
  26. publicvoidsetSession(Mapsession){
  27. this.session=session;
  28. }
  29. publicstaticStringgetStatic(){
  30. return”这是LoginAction中的一个静态方法”;
  31. }
  32. publicStringgetCommon(){
  33. return”这是LoginAction中的一个普通方法”;
  34. }
  35. @Override
  36. publicStringexecute()throwsException{
  37. if(user.getUsername().trim().equalsIgnoreCase(“admin”)&&user.getPassword().equals(“jadyer”)){
  38. testList.add(“list11″);
  39. testList.add(“list22″);
  40. testList.add(“list33″);
  41. testList.add(“list44″);
  42. testList.add(“list55″);
  43. testSet.add(“set11″);
  44. testSet.add(“set22″);
  45. testSet.add(“set33″);
  46. testSet.add(“set22″);
  47. testSet.add(“set11″);
  48. testMap.put(“m11″,”map11″);
  49. testMap.put(“m22″,”map22″);
  50. testMap.put(“m33″,”map33″);
  51. testMap.put(“m44″,”map44″);
  52. testMap.put(“m55″,”map55″);
  53. stus.add(newStudent(“张三”,88));
  54. stus.add(newStudent(“李四”,77));
  55. stus.add(newStudent(“王五”,66));
  56. stus.add(newStudent(“马六”,55));
  57. request.put(“req”,”这是通过OGNL中的#号获取的request属性范围的值”);
  58. session.put(“ses”,”这是通过OGNL中的#号获取的session属性范围的值”);
  59. request.put(“BB”,”这是通过OGNL中的#号获取的request属性范围的BB”);
  60. session.put(“BB”,”这是通过OGNL中的#号获取的session属性范围的BB”);
  61. returnSUCCESS;
  62. }else{
  63. returnINPUT;
  64. }
  65. }
  66. }

转自:http://blog.csdn.net/jadyer/article/details/6174555