在这里我们来讨论一下ognl表达式的3个功能:
一、利用ognl表达式创建list/Map对象
二、判断某个对象是否存在于集合中
三、通过一定的规则来获取集合中的子集
/分---------------割----------------线-----------------/
一:在El表达式中,我们要弄到一个集合对象的做法是在servlet中创建一个集合,然后给它命名,然后放到某个域对象中,然后在jsp中利用El表达式得到这个集合。
1、但是OGNL可以直接在jsp中创建list。这个要借助标签
代码如下:
<s:set var="list" value="{'a','b','c'}"></s:set>
<s:debug></s:debug>
然后访问http://localhost:8080/struts2Day03/ognl.jsp
点开debug后,使用快速查找 list
其实标签中还有一个scope属性:就是指存放的范围,翻阅tld文件,看到
<description><![CDATA[The scope in which to assign the variable. Can be <b>application</b>, <b>session</b>, <b>request</b>, <b>page</b>, or <b>action</b>.]]></description>
可以存在5个范围,默认的是action范围。
获取里面的内容:
<s:iterator value="#list" var="l">
<s:property value="#l"/>
</s:iterator>
2、创建Map
<s:set var="map1" value="#{'a':'valueA','b':'valueB'}" "></s:set><br/>
如果要读取Map中的内容,尽量使用标签,也可以使用El表达式
<s:iterator value="#map1" var="me">
<s:property value="#me.key"/>=<s:property value="#me.value"/>
</s:iterator>
El表达式的形式为:
<c:forEach items="${map1}" var="me">
<c:out value="${me.key}=${me.value}"></c:out>
</c:forEach>
/分---------------割----------------线-----------------/
二、判断某个对象是否存在于集合:
借助于标签,代码如下:
<s:set value="{'aaa','bbb'}" var="list"></s:set>
<s:if test="'aaa' in #list">
yes
</s:if>
因为ognl表达式还有直接创建list/map的功能所以也可以写成这样:
<s:if test="'aaa' in {'aaa','bbb'}">
yes
</s:if>
如果存在,就显示标签中的内容,如果不存在就不显示,
除了用In ,还可以用 not in
<s:if test="'aaa' not in {'aaa','bbb'}">
不存在
</s:if>
其实里面的道理,跟Java中的If判断是一个意思,只不过In/not in 在这里被当作关键字
/分---------------割----------------线-----------------/
三、通过一定的规则来获取集合中的子集
常用的符号有 ? ^ $
上面3个符号分别代表 符合逻辑的所有元素、符合逻辑的第一个元素、符合逻辑的最后一个元素。
那么我们就拿书本来做例子,本来有3本书,他们的价格不一样,通过价格来筛选出所有符合逻辑的元素
(1)在struts.xml文件配置如下:
<action name="ognlAction2" class="cn.ansel.domain.bookAction" method="showAllBooks">
<result name="success">/success.jsp</result>
</action>
(2)根据struts.xml配置文件,创建相关的类,方法,页面
这是book类:
package cn.ansel.domain;
import java.io.Serializable;
public class Book implements Serializable {
private String name;
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Book(String name, float price) {
super();
this.name = name;
this.price = price;
}
public Book() {
}
}
然后是action类:
package cn.ansel.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class bookAction extends ActionSupport implements Serializable {
private List<Book> books;
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public String showAllBooks(){
//这里为了方便,没有写mvc三层架构,就直接new arrayList当作从数据库中取出的内容。
books=new ArrayList<Book>();
books.add(new Book("猫生十年", 5.5f));
books.add(new Book("白夜行", 45.5f));
books.add(new Book("神秘事件录", 35.5f));
return SUCCESS;
}
}
然后是页面:
<s:iterator value="books.{?#this.price>10.0f}" var="book">
<s:property value="book.name"/>:<s:property value="book.price"/>
</s:iterator>
输出的结果是:
在上面可以看到,books.{?#this.price>10.0f}
,其实ognl的筛选功能就出现在.{?#this.price>10.0f}
中,用大括号把规则括起来,?代表符合该规则的所有元素,由于这里在迭代,所以要用到当前对象this 当然,关于迭代的标签,为什么要用#this呢,不是说books对象存在于valueStack中吗?那么为什么要用?
这是因为在迭代的时候,books本来是在valueStack中的,但是在被迭代到的过程中,当前对象就会被弹栈,就存在于actionContext中了,所以要指明名称空间。
this代表当前对象,this.price代表当前的对象的price属性,这样来理解就明了了。