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>