OGNL表达式和Struts2标签

来源:互联网 发布:php参考手册中文版下载 编辑:程序博客网 时间:2024/06/07 18:20

OGNL的全称是Object Graph Navigation Language(对象图形导航语言),它是一种强大的表达式语言,开发者可以通过简单一致的表达式语法来读取和设置java对象的属性值,调用对象的方法,遍历整个对象的结构。

操作对象!

OGNL有一个上下文(Context)概念,通俗的说就是一个Map结构,它实现了java.util.Map接口,在struts2中上下文(Context)的实现为ActionContext。即Struts2中OGNL Context实现者为ActionContext,它的结构示意图如下:


当Struts2接受一个请求时,会迅速创建ActionContext,然后创建ValueStack,再创建action。接着把action存放到ValueStack中,所以action中的实例变量可以被OGNL表达式直接访问。

OGNL表达式访问各个命名空间的属性:

1.访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application、#Session...

2.另外OGNL会设定一个根对象(root对象),在struts2中根对象就是ValueStack(值栈)。如果要访问根对象(即值栈ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。

3.在struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是存放单个值,而是存放一组对象。在OgnlValueStack类里面有一个List类型的root变量,就是使用它来存放一组对象,如图:


4.在root变量中处于第一位的对象叫做栈顶对象。通常我们在OGNL表达式里直接写上熟悉你的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象开始寻找,依次往下访问,知道找到为止。

如:要访问存在栈顶中的一个name属性,我们不需要用到#命名空间的方式,可以直接使用对象属性名称的方式访问,即写个name即可,但是这样写又是无效的,在struts2中,OGNL表达式需要配合struts2标签才可以使用,应该写成这样:<s:property value="name">,这个name就是OGNL表达式。

5.访问值栈ValueStack中的对象,除了直接写属性名称以外,还可以使用EL表达式直接访问,如上面的name,可以这样访问:${name}。

注:EL表达式只限于访问值栈ValueStack中的对象的属性,如果要访问其他域的属性还得使用#命名空间的方式。

Application对象:用于访问ServletContext,例如:#application.userName或者#application['userName'](注【】的形式在一些特殊字符的时候使用,如#applicaiton['u-name']),这样相当于调用了ServletContext的getAttribute("username");

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

request对象:用来访问HttpServletRequest属性,例如:#request.userName或者#request['userName'],相当于调用request.getAttribute("userName");

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

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


在JSP中使用strus2的标签,必须要引入标签声明:

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

1.set标签:用于将某个值放入指定的范围。

参数:


注:如果没有设置scope范围,那么默认为OGNL Context(访问时不需要命名空间,使用#即可)。

测试代码:

<body>   <s:set name="age" value="22"></s:set>  </body>

注:上述代码没有指定范围,即将age放入OGNL Context中,访问时使用#age即可。

2.property标签:用于输出指定的值:

value属性:可选,指定需要输出的属性值,如果没有该属性,则默认输出ValueStack栈顶的值(这个非常重要,有些时候不写value也可以输出,是因为要访问的属性在栈顶)。

测试代码1(访问request范围的属性):

<body><%request.setAttribute("name", "习近平");%> <!-- 访问request范围内的属性,要使用#命名空间的形式 -->名称:<s:property value="#request.name"/>   </body>

效果:


测试代码2(访问Session范围的属性):

 <body><%session.setAttribute("name", "李克强");%> <!-- 访问session范围内的属性,要使用#命名空间的形式 -->名称:<s:property value="#session.name"/>   </body>

效果:


测试代码3(访问值栈中的属性):

/** * 在请求访问action的时候,系统会迅速创建ActionContext->valueStack->action * 并且把action存放在valueStack中,这就是为什么OGNL表达式可以直接以属性名称的方式访问属性。 * 因为action存放在了valueStack中。 * @author Liao * */public class UserAction extends ActionSupport {private static final long serialVersionUID = 1L;private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public String execute(){this.setName("胡锦涛");return this.SUCCESS;}}

在界面访问:

 <body><!-- 访问valueStack中的属性,不需要使用#命名空间的形式,直接通过属性名的方式即可访问 -->名称:<s:property value="name"/> <br><!-- 值栈的值也可以直接通过EL表达式来访问 -->通过EL表达式获取的名称:${name}  </body>


效果:


3.Iterator迭代标签:用于遍历集合(java.util.Collection)或者枚举值(java.util.iterator)。

参数:


注:value为可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合。

在演示之前我们先看另外一个知识点:通过OGNL表达式来创建List/Map集合。

测试代码:

<body>  <!-- 通过OGNL可以创建List和Map集合value="{'邓小平','胡锦涛','习近平'}"表示一个List集合 -->  <s:set  name="list" value="{'邓小平','胡锦涛','习近平'}"/>    <!-- 上述集合没有指定范围就表示OGNL Context范围内的变量,使用#即可 ,iterator标签中的value表示要迭代的集合-->  <s:iterator value="#list">  <!-- 注:Iterator标签在迭代集合时,会把当前迭代的对象放在值栈的栈顶,所以使用property标签输出时可以不用value -->  <s:property /><br>  </s:iterator>  </body>

注:一定要记住,iterator标签在迭代集合时会把当前迭代的对象放在值栈的栈顶,这就是为什么使用property输出值时可以不写value属性的原因。

 效果:


使用OGNL创建Map集合:

测试代码【通过OGNL可以创建List和Map集合value="#{'key1':'邓小平','key2':'胡锦涛','key3':'习近平'}"表示一个map集合(注意书写方式)】:

测试代码:

<body><s:set name="maps" value="#{'key1':'邓小平','key2':'胡锦涛','key3':'习近平'}" /><!-- 上述集合没有指定范围就表示OGNL Context范围内的变量,使用#即可 ,iterator标签中的value表示要迭代的集合--><s:iterator value="#maps"><!-- 注:Iterator标签在迭代集合时,会把当前迭代的对象放在值栈的栈顶,所以使用property标签输出时可以不用value --><s:property value="key" />=<s:property value="value" /></br></s:iterator></body>

效果:


OGNL表达式的投影功能,常用操作符:

1.?表示获得所有符合逻辑的元素。

2.^表示符合逻辑的第一个元素。

3.$表示符合逻辑的最后一个元素。

测试案例:

User对象:

public class User {private Integer uid;private String uname;private Integer age;public User() {}public User(Integer uid, String uname, Integer age) {this.uid = uid;this.uname = uname;this.age = age;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}}

UserAction.java:

/** * 在请求访问action的时候,系统会迅速创建ActionContext->valueStack->action * 并且把action存放在valueStack中,这就是为什么OGNL表达式可以直接以属性名称的方式访问属性。 * 因为action存放在了valueStack中。 * 这个类中的users属性可以直接通过属性名称的方式访问 * @author Liao * */public class UserAction extends ActionSupport {private static final long serialVersionUID = 1L;private List<User> users;public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}public String execute(){users = new ArrayList<User>();users.add(new User(1, "习近平", 20));users.add(new User(1, "胡锦涛", 30));users.add(new User(1, "邓小平", 40));return this.SUCCESS;}}

前台投影测试:

<body><!-- users是action中的属性,即存放在ValueStack中,所以访问users不需要使用#命名空间的形式 --><s:iterator value="users.{?#this.age > 30}"><s:property value="uname" />:<s:property value="age" /></br></s:iterator></body>

注:users是action中的属性,当然也是ValueStack中的对象,所以可以用属性名称的方式直接访问。在上述代码中,直接在集合后紧跟.{}运算符表明用于取出该集合的子集,{}的表达式用于获取符合条件的元素,this指的是为了从大集合users帅选数据到小集合,需要对大集合users进行迭代,this代表当前迭代的元素。

效果:


iterator标签中的status属性用来指定迭代时的IteratorStatus实例,该方法包含如下集合方法:

int getCount(),返回当前迭代了几个元素。
int getIndex(),返回当前迭代元素的索引。
boolean isEven(),返回当前被迭代元素的索引是否是偶数
boolean isOdd(),返回当前被迭代元素的索引是否是奇数
boolean isFirst(),返回当前被迭代元素是否是第一个元素。
boolean isLast(),返回当前被迭代元素是否是最后一个元素。

有了这些方法,我么可以做一些特殊效果:

测试代码:

 <body><s:set name="list" value="{'邓小平','胡锦涛','习近平'}" /><s:iterator value="#list" status="s"><!-- 如果是奇数就为红色,否则为蓝色 --><font color=<s:if test="#s.odd">red</s:if><s:else>blue</s:else>><s:property/></font></s:iterator>    </body>

效果:


4.if elseif else 标签:执行基本的条件流转。

参数:

测试代1:

<body>     <s:set name="age" value="22"></s:set>      <!-- 使用ognl接收值 -->   <s:if test="#age > 20">   您的青春已经让狗给吃了!   </s:if>      <s:elseif test="#age > 35">   七年之痒,勿出轨!   </s:elseif>      <s:else>   青春年华,无限风光!   </s:else>     </body>

效果:



OGNL表达式可以使用in和not in两个元素符号,in表达式用来判断某个元素是否在指定的集合对象中,not in判断某个元素是否不在某个集合对象中。

测试代码2:

 <body>   <!-- OGNL表达式in的测试 -->   <s:if test="'liao' in {'liao','zhong','min'}">   您中大奖啦!   </s:if>   <s:else>   您被坑啦!   </s:else>      <!-- OGNL表达式not in的测试 -->   <s:if test="'liao' not in {'lavimer','hello'}">   你不在啊!   </s:if>   <s:else>   你在啊!   </s:else>  </body>


注:<s:select>下拉框、<s:checkboxlist>复选框、<s:radio>单选框在Web开发中经常使用,将在后面的文章中以专题的形式详细讨论。

0 0
原创粉丝点击