OGNL使用详解二:Struts2的OGNL应用
在上一篇的博文基础上,现在来看一下OGNL在Struts2中的应用。
在上一篇文章中,我提到了,OgnlContext有一个称之为root的根对象,ognl取值默认从root中取。
而在Struts2中的根对象就是:ValueStack(请记住,在Struts2中,OnglContext的root对象永远都是ValueStack)
现在来解释一下ValueStack是什么。
在Struts2中,ValueStack是一个值栈接口,可以将多个bean压进ValueStack中。可以使用EL表达式来取出ValueStack里面的东西与计算等等。ValueStack作为一个栈,放进去对象后。在查找时,必须从栈顶向栈底查找,一旦在栈顶查找到了,直接返回,不会再向栈底方向继续查找了。例如:先放了一个person对象(属性:name,address),再放了一个dog对象(属性:name,size)。此时查找name属性,就会把dog的name属性取出来。查找address时,dog没找到这个属性,才会向栈底方向继续查找,找到person的address并返回。如果查找person对象的name,[1].name,过滤栈顶元素,从栈顶第二个元素开始的栈里面寻找name属性,就会找到了。
现在再来介绍一下ValueStack子栈的概念,在ValueStack中,栈顶元素索引是0,栈底元素索引是n。[0]返回从第0个元素到第n个元素的子栈,即当前的ValueStack。[2]返回从第3个元素到第n个元素的子栈.用这个方式过滤栈顶的部分元素,达到查找某个属性的效果。
在Struts2中, OgnlValueStack实现了ValueStack接口,而在ValueStack中,在Struts2的任何流程中,ValueStack中最顶层的对象一定是action对象。因此在jsp用OGNL直接写某个action的属性可以直接取值。就是因为ValueStack是OgnlContext的根对象,无需写#,默认就是根对象ValueStack。而action对象永远是ValueStack的栈顶元素,所以我们写一个属性名字,就会从action对象中取出来了。如果这个action中没这个 属性,才会往下面找。
Struts2在OgnlContext中初始化放进去了几个命名对象(没有放在跟对象ValueStack中,而是放在OgnlContext中,与ValueStack平级):request,application,parameters,session,attr 。
parameters:用户向action访问携带的参数,例如:#parameters.username(相当于request.getParameter("username"))
request:jsp内置对象之一,例如:#parameters.username(相当于request.getAttribute("username"))
session:jsp内置对象之一,例如:#session.username(相当于session.getAttribute("username"))
application:jsp内置对象之一,例如:#application.username(相当于application.getAttribute("username"))
<attr:不是一个实际的对象,在查找时,现在pageContext当前页面中找,再去request,再去session,再去application找,例如:#attr.username
好了,说了这么多,太枯燥了,直接上代码!
首先看一下bean实体的两个类:
<span style="font-size:24px;">package struts2.ognl.bean;
/**
*
* @author wangjian
*
*/
public class Cat {
private String name;
private int age;
private String color;
public Cat(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public Cat() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
</span>
<span style="font-size:24px;">package struts2.ognl.bean;
import java.util.Map;
/**
*
* @author wangjian
*
*/
public class Person {
private String name;
private int age;
private String address;
private String[] friends;
private Cat cat;
private Map<String, String> map;
public Person(String name, int age, String address, String[] friends,
Cat cat, Map<String, String> map) {
this.name = name;
this.age = age;
this.address = address;
this.friends = friends;
this.cat = cat;
this.map = map;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String[] getFriends() {
return friends;
}
public void setFriends(String[] friends) {
this.friends = friends;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}
</span>
接下来看一下action:
<span style="font-size:24px;">
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import struts2.ognl.bean.Cat;
import struts2.ognl.bean.Person;
import com.opensymphony.xwork2.ActionSupport;
/**
*
* @author wangjian
*
*/
public class OgnlAction extends ActionSupport implements RequestAware,
SessionAware, ApplicationAware {
private String username;
private String password;
private Map<String, Object> requestMap;
private Map<String, Object> sessionMap;
private Map<String, Object> applicationMap;
private List<Person> list;
public List<Person> getList() {
return list;
}
public void setList(List<Person> list) {
this.list = list;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setRequest(Map<String, Object> arg0) {
System.out.println("setRequest invoked");
this.requestMap = arg0;
}
public void setSession(Map<String, Object> arg0) {
System.out.println("setSession invoked!");
this.sessionMap = arg0;
}
public void setApplication(Map<String, Object> arg0) {
this.applicationMap = arg0;
}
@Override
public String execute() throws Exception {
Thread.sleep(20000);
requestMap.put("hello", "world");
sessionMap.put("hello", "hello");
applicationMap.put("hello", "hello world");
Cat cat1 = new Cat("cat1", 20, "red");
Cat cat2 = new Cat("cat2", 30, "blue");
String[] friends1 = { "test1", "test2", "test3" };
String[] friends2 = { "welcome1", "welcome2", "welcome3" };
Map<String, String> map1 = new HashMap<String, String>();
Map<String, String> map2 = new HashMap<String, String>();
map1.put("test1", "test1");
map1.put("test2", "test2");
map2.put("hello1", "hello1");
map2.put("hello2", "hello2");
Person person1 = new Person("zhangsan", 20, "beijing", friends1, cat1,
map1);
Person person2 = new Person("lisi", 30, "shanghai", friends2, cat2,
map2);
list = new ArrayList<Person>();
list.add(person1);
list.add(person2);
return SUCCESS;
}
}
</span>
下面来看一下在jsp网页中,如何通过OGNL来取得action传过来的信息。
<span style="font-size:24px;"><%@ page language="java"
import="java.util.*, com.opensymphony.xwork2.* "
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>OGNL(Object Graph Navigation Language)对象图导航语言OGNL</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<br>username:
<s:property value="username" />
<br> password:
<s:property value="password" />
<br> ----------------------------------------
<br> username:
<s:property value="#parameters.username" />
<br> password:
<s:property value="#parameters.password" />
<br> ----------------------------------------
<br> request:
<s:property value="#request.hello" />
<br> session:
<s:property value="#session.hello" />
<br> application:
<s:property value="#application.hello" />
<br> attr:
<s:property value="#attr.hello" />
<br> ----------------------------------------
<br> request:
<%=((Map) ActionContext.getContext().get("request"))
.get("hello")%><br> session:
<%=ActionContext.getContext().getSession().get("hello")%><br>
application:
<%=ActionContext.getContext().getApplication().get("hello")%><br>
attr:
<%=((Map) ActionContext.getContext().get("attr"))
.get("hello")%>
<br> ----------------------------------------
<br> person1: address:
<s:property value="list[0].address" />
<br> person2: age:
<s:property value="list[1].age" />
<br> person1: cat1: name:
<s:property value="list[0].cat.name" />
<br> size:
<s:property value="list.size" />
<br> isEmpty:
<s:property value="list.isEmpty()" />
<br> ----------------------------------------
<br> person1: address:
<%=((OgnlAction) ActionContext.getContext().getValueStack()
.peek()).getList().get(0).getAddress()%><br> person2: age:
<%=((OgnlAction) ActionContext.getContext().getValueStack()
.peek()).getList().get(1).getAge()%><br> person1: cat1: name:
<%=((OgnlAction) ActionContext.getContext().getValueStack()
.peek()).getList().get(0).getCat().getName()%><br>
----------------------------------------
<br> person2:friend:
<s:property value="list[1].friends[2]" />
<br> person2:friend:
<%=((OgnlAction) ActionContext.getContext().getValueStack()
.peek()).getList().get(1).getFriends()[2]%><br>
----------------------------------------
<br> person2: map2:
<s:property value="list[1].map['hello2']" />
<br> ----------------------------------------
<br> filtering:
<s:property value="list.{? #this.name.length() > 2}[1].name" />
<br> ----------------------------------------
<br>
<s:iterator value="list.{? #this.name.length() > 2}">
<s:property value="name" />
<br>
<s:property value="cat.color" />
<br>
<s:property value="friends[0]" />
<br>
</s:iterator>
----------------------------------------
<br> projection:
<br>
<s:iterator value="list.{age}">
<s:property />
<br>
</s:iterator>
</body>
</html>
</span>