Struts 2的OGNL表达式

来源:http://www.24xuexi.com/w/2011-04-26/88911.html

Struts 2的OGNL表达式

标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不使用Struts 2的OGNL表达式),如果OGNL上下文(OgnlContext Map类型)有两个对象:foo对象,在OgnlContext中名称为foo;bar对象,在OgnlContext中名称为bar。同时foo对象被设置为根对象(root)。则利用下面的OGNL表达式求值:

// 返回foo.getBlah()

#foo.blah

//返回bar.getBlah()

#bar.blah

//返回foo.getBlah() ,因为foo为根对象

blah

★ 说明 ★

使用OGNL是非常简单的,如果要访问的对象不是根对象,如示例中的bar对象,则需要使用命名空间,用“#”来标识,如“#bar”;如果访问一个根对象,则不用指定命名空间,可以直接访问根对象的属性。

在Struts 2框架中,值栈(Value Stack)就是OGNL的根对象,假设值栈中存在两个对对象实例:Man和Animal,这两个对象实例都有一个name属性,Animal有一个species属性,Man有一个salary属性,假设Animal在值栈的顶部,Man在Animal后面,下面的代码片断会帮助读者更好地理解OGNL表达式:

// 调用animal.getSpecies()

species

// 调用man.getSalary()

salary

// 调用animal.getName(),因为Animal位于值栈的顶部

name

最后一行示例代码,返回的是animal.getName()返回值,即返回了Animal的name属性,因为Animal是值栈的顶部元素,OGNL将从顶部元素搜索,所以会返回Animal的name属性值。如果要获得Man的name值,则需要如下代码:

man.name

Struts 2允许在值栈中使用索引,示例代码如下所示:

[0].name // 调用animal.getName()

[1].name // 调用man.getName()

★ 说明注意 ★

使用索引,并不是直接获得指定的元素,而是从指定的索引位置搜索。

Struts 2中的OGNL Context是ActionContext,如图8.2所示。

图8.2 Struts 2的OGNL Context结构示意图

★ 说明 ★

图8.2只是说明Struts 2的OGNL Context结构,实际上Context还包含其他对象。

由于值栈是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,则可以直接通过下面的代码访问值栈中的属性:

//获得值栈中的foo属性

${foo}

如果访问其他Context中的对象,由于不是根对象,在访问时,需要加#前缀。

― application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用Servlet的getAttribute("username")。

― session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")。

― request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.get力Attribute ("userName")。

― parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")。

― attr对象:用于按page-request-session-application顺序访问其属性。

8.2.2 OGNL的集合操作

如果需要一个集合元素的时候(例如List对象或者Map对象),可以使用OGNL中同集合相关的表达式。

可以使用如下代码直接生成一个List对象:

{e1,e2,e3…}

该OGNL表达式中,直接生成了一个List对象,该List对象中包含3个元素:e1、e2和e3。如果需要更多的元素,可以按照这样的格式定义多个元素,多个元素之间使用逗号隔开。

如下代码可以直接生成一个Map对象:

#{key1:value1,key2:value2,…}

Map类型的集合对象,使用key-value格式定义,每个key-value元素使用冒号标识,多个元素之间使用逗号隔开。

对于集合类型,OGNL表达式可以使用in和not in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,如代码8.3所示。

代码8.3 使用OGNL集合操作符

<s:if test="'foo' in {'foo','bar'}">

muhahaha

</s:if>

<s:else>

boo

</s:else>

<s:if test="'foo' not in {'foo','bar'}">

muhahaha

</s:if>

<s:else>

boo

</s:else>

除了in和not in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。

― ?:获得所有符合逻辑的元素。

― ^:获得符合逻辑的第一个元素。

― $:获得符合逻辑的最后一个元素。

例如代码:

person.relatives.{? #this.gender == 'male'}

该代码可以获得person的所有性别为male的relatievs集合。

8.2.3 Lambda表达式

OGNL支持基本的Lambda表达式语法,通过Lambda表达式语法,可以在OGNL中使用一些简单的函数。例如:

Fibonacci:

if n==0 return 0;

elseif n==1 return 1;

else return fib(n-2)+fib(n-1);

fib(0) = 0

fib(1) = 1

fib(11) = 89

开发者可以使用Lambda表达式语法:

<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />

JSP视图

showognl.jsp是使用了OGNL表达式的JSP视图,视图用来显示Action中处理的各种信息,读者可以看到,使用OGNL表达式,代码更加简洁和直观,如代码8.5所示。

代码8.5 使用OGNL表达式的JSP视图

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>

<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Struts2 OGNL 演示</title>

</head>

<body>

<h3>访问OGNL上下文和Action上下文</h3>

<!-使用OGNL访问属性值-->

<p>parameters: <s:property value="#parameters.msg" /></p>

<p>request.msg: <s:property value="#request.msg" /></p>

<p>session.msg: <s:property value="#session.msg" /></p>

<p>application.msg: <s:property value="#application.msg" /></p>

<p>attr.msg: <s:property value="#attr.msg" /></p>

<hr />

<h3>用于过滤和投影(projecting)集合</h3>

<p>年龄大于20</p>

<ul>

<!-判断年龄-->

<s:iterator value="persons.{?#this.age>20}">

<li><s:property value="name" /> - 年龄:<s:property value="age" /></li>

</s:iterator>

</ul>

<p>姓名为pla1的年龄: <s:property value="persons. {?#this.name=='pla1'} .{age}[0]"/></p>

<hr />

<h3>构造Map</h3>

<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />

<p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>

</body>

</html>

OGNL中的#、%和$符号

#、%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分。在这里笔者简单介绍它们的相应用途。

1.#符号

#符号的用途一般有三种。

― 访问非根对象属性,例如示例中的#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute("msg")。

― 用于过滤和投影(projecting)集合,如示例中的persons.{?#this.age>20}。

― 用来构造Map,例如示例中的#{'foo1':'bar1','foo2':'bar2'}。

2.%符号

%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。如下面的代码所示:

<h3>构造Map</h3>

<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />

<p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>

<p>不使用%:<s:url value="#foobar['foo1']" /></p>

<p>使用%:<s:url value="%{#foobar['foo1']}" /></p>

运行界面如图8.4所示。

3.$符号

$符号主要有两个方面的用途。

― 在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。

― 在Struts 2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:

<validators>

<field name="intb">

<field-validator type="int">

<param name="min">10</param>

<param name="max">100</param>

<message>BAction-test校验:数字必须为${min}为${max}之间!</message>

</field-validator>

</field>

</validators>



阅读更多
个人分类: struts
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭