OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,能通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
一、为什么要使用OGNL
视图层的表达式语言通常是用来简化数据的访问操作,取代Java脚本代码,提供更清晰的视图层实现。比如,要获取user对象的age属性,利用OGNL表达式可以写成:
<s:property value="user.age"/>
而如果要换做Java脚本代码,则需要写成:
<%@ page import="com.chongqing.model.User" %> <% User user = (User)request.getAttribute("user"); String age = user.getAge(); out.print(age); %>
可以看出,利用OGNL表达式会更加清晰和简洁。
二、值栈(ValueStack)
OGNL有一个上下文(Context)的概念,说白了上下文就是一个MAP结构,它实现了Java.utils.Map接口,在Struts2中上下文(Context)的实现为ActionContext ,它结构示意图如下:
|--request
|--application
OGNL context ------ | ValueStack(值栈,它是根对象)
|--session
|--attr
|--parameters
当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。
访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application、#session等
另外OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈) 。如果要访问根对象(即ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。
可以通过<s:debug></s:debug>标签在浏览器上看到Context的内容,其实OGNL表达式就是用来访问Context中的内容。
三、OGNL表达式
OGNL表达式的语法多且杂,要全部总结出来有点困难,这里我偷一点懒,通过一个例子来说明,以后查阅也会方便一些。
OgnlAction类:
1 package com.chongqing.ognl; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.HashSet; 6 import java.util.List; 7 import java.util.Map; 8 import java.util.Set; 9 10 import com.opensymphony.xwork2.ActionSupport; 11 12 public class OgnlAction extends ActionSupport { 13 private Cat cat; 14 private Map<String, Dog> dogMap = new HashMap<String, Dog>(); 15 16 private Set<Dog> dogs = new HashSet<Dog>(); 17 18 private String password; 19 20 private User user; 21 private String username; 22 23 private List<User> users = new ArrayList<User>(); 24 25 public OgnlAction() { 26 users.add(new User(1)); 27 users.add(new User(2)); 28 users.add(new User(3)); 29 30 dogs.add(new Dog("dog1")); 31 dogs.add(new Dog("dog2")); 32 dogs.add(new Dog("dog3")); 33 34 dogMap.put("dog100", new Dog("dog100")); 35 dogMap.put("dog101", new Dog("dog101")); 36 dogMap.put("dog102", new Dog("dog102")); 37 38 } 39 40 public String execute() { 41 return SUCCESS; 42 } 43 44 public Cat getCat() { 45 return cat; 46 } 47 48 public Map<String, Dog> getDogMap() { 49 return dogMap; 50 } 51 52 public Set<Dog> getDogs() { 53 return dogs; 54 } 55 56 public String getPassword() { 57 return password; 58 } 59 60 public User getUser() { 61 return user; 62 } 63 64 public String getUsername() { 65 return username; 66 } 67 68 public List<User> getUsers() { 69 return users; 70 } 71 72 public String m() { 73 return "hello"; 74 } 75 76 public void setCat(Cat cat) { 77 this.cat = cat; 78 } 79 80 public void setDogMap(Map<String, Dog> dogMap) { 81 this.dogMap = dogMap; 82 } 83 84 public void setDogs(Set<Dog> dogs) { 85 this.dogs = dogs; 86 } 87 88 public void setPassword(String password) { 89 this.password = password; 90 } 91 92 public void setUser(User user) { 93 this.user = user; 94 } 95 96 public void setUsername(String username) { 97 this.username = username; 98 } 99 100 public void setUsers(List<User> users) { 101 this.users = users; 102 } 103 }
User类:
1 package com.chongqing.ognl; 2 3 public class User { 4 private int age = 8; 5 6 public User() { 7 8 } 9 10 public User(int age) { 11 super(); 12 this.age = age; 13 } 14 15 16 public int getAge() { 17 return age; 18 } 19 20 public void setAge(int age) { 21 this.age = age; 22 } 23 24 @Override 25 public String toString() { 26 return "user" + age; 27 } 28 }
Cat类:
1 package com.chongqing.ognl; 2 3 public class Cat { 4 5 private Dog friend; 6 7 public Dog getFriend() { 8 return friend; 9 } 10 11 public void setFriend(Dog friend) { 12 this.friend = friend; 13 } 14 15 public String miaomiao() { 16 return "miaomiao"; 17 } 18 }
Dog类:
1 package com.chongqing.ognl; 2 3 public class Dog { 4 5 private String name; 6 7 public Dog() { 8 9 } 10 11 public Dog(String name) { 12 super(); 13 this.name = name; 14 } 15 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 @Override 25 public String toString() { 26 return "dog: " + name; 27 } 28 }
S类:
1 package com.chongqing.ognl; 2 3 public class S { 4 public static String STR = "STATIC STRING"; 5 6 public static String s() { 7 return "static method"; 8 } 9 }
ognl.jsp:
<?xml version="1.0" encoding="GB18030" ?> <%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!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> <meta http-equiv="Content-Type" content="text/html; charset=GB18030" /> <title>OGNL表达式语言学习</title> </head> <body> <ol> <%-- 访问普通方法和属性: 1、通过域模型的方式只有传入参数,才会构造对象,或者直接在action中new也可以 --%> <li>访问值栈中的action的普通属性: username = <s:property value="username"/> </li> <li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user[‘age‘]"/> | <s:property value="user[\"age\"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li> <li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name"/></li> <li>访问值栈中对象的普通方法:<s:property value="password.length()"/></li> <li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li> <li>访问值栈中action的普通方法:<s:property value="m()" /></li> <hr /> <%-- 访问静态方法和属性: 1、OGNL表达式语言访问静态方法,需要在Struts2.xml配置allowStaticMethodAccess为true 2、@@max(2,3)这种方式只能访问Math的静态方法 --%> <li>访问静态方法:<s:property value="@[email protected]()"/></li> <li>访问静态属性:<s:property value="@[email protected]"/></li> <li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li> <hr /> <li>访问普通类的构造方法:<s:property value="new com.chongqing.ognl.User(8)"/></li> <hr /> <%-- 访问集合: 1、{}大括号可以表示一个集合 2、因为在Set中没有排序所以不能用下标访问 3、访问容器的大小用方法size()和属性size都行 --%> <li>访问List:<s:property value="users"/></li> <li>访问List中某个元素:<s:property value="users[1]"/></li> <li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li> <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li> <li>访问Set:<s:property value="dogs"/></li> <li>访问Set中某个元素:<!--<s:property value="dogs[1]"/>--></li> <li>访问Map:<s:property value="dogMap"/></li> <li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap[‘dog101‘]"/> | <s:property value="dogMap[\"dog101\"]"/></li> <li>访问Map中所有的key:<s:property value="dogMap.keys"/></li> <li>访问Map中所有的value:<s:property value="dogMap.values"/></li> <li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li> <hr /> <%-- 投影: 1、投影其实就是对集合过滤选择 2、?表示选取过滤后的所有元素 3、^表示选取过滤后的第一个元素 4、$表示选取过滤后的最后一个元素 --%> <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li> <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li> <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li> <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li> <hr /> <li>[]:<s:property value="[0].username"/></li> </ol> <s:debug></s:debug> </body> </html>
访问的URL为:
http://localhost:8080/Struts2_OGNL/ognl.action?username=u&password=p&user.age=11&cat.friend.name=oudy
结果为: