首页 > 代码库 > Struts2中OGNL表达式的用法

Struts2中OGNL表达式的用法

OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,能通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。

一、为什么要使用OGNL

视图层的表达式语言通常是用来简化数据的访问操作,取代Java脚本代码,提供更清晰的视图层实现。比如,要获取user对象的age属性,利用OGNL表达式可以写成:

<s:property value="http://www.mamicode.com/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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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="http://www.mamicode.com/username"/> </li>
		<li>访问值栈中对象的普通属性(get set方法):<s:property value="http://www.mamicode.com/user.age"/> | <s:property value="http://www.mamicode.com/user[‘age‘]"/> | <s:property value="http://www.mamicode.com/user[/"age\"]"/> | wrong: <%--<s:property value="http://www.mamicode.com/user[age]"/>--%></li>
		<li>访问值栈中对象的普通属性(get set方法): <s:property value="http://www.mamicode.com/cat.friend.name"/></li>
		<li>访问值栈中对象的普通方法:<s:property value="http://www.mamicode.com/password.length()"/></li>
		<li>访问值栈中对象的普通方法:<s:property value="http://www.mamicode.com/cat.miaomiao()" /></li>
		<li>访问值栈中action的普通方法:<s:property value="http://www.mamicode.com/m()" /></li>
		<hr />
		
		<%-- 访问静态方法和属性:
		1、OGNL表达式语言访问静态方法,需要在Struts2.xml配置allowStaticMethodAccess为true
		2、@@max(2,3)这种方式只能访问Math的静态方法
		 --%>
		<li>访问静态方法:<s:property value="http://www.mamicode.com/@com.chongqing.ognl.S@s()"/></li>
		<li>访问静态属性:<s:property value="http://www.mamicode.com/@com.chongqing.ognl.S@STR"/></li>
		<li>访问Math类的静态方法:<s:property value="http://www.mamicode.com/@@max(2,3)" /></li>
		<hr />
		<li>访问普通类的构造方法:<s:property value="http://www.mamicode.com/new com.chongqing.ognl.User(8)"/></li>
		<hr />
		
		<%-- 访问集合:
		1、{}大括号可以表示一个集合
		2、因为在Set中没有排序所以不能用下标访问
		3、访问容器的大小用方法size()和属性size都行	
		 --%>
		<li>访问List:<s:property value="http://www.mamicode.com/users"/></li>
		<li>访问List中某个元素:<s:property value="http://www.mamicode.com/users[1]"/></li>
		<li>访问List中元素某个属性的集合:<s:property value="http://www.mamicode.com/users.{age}"/></li>
		<li>访问List中元素某个属性的集合中的特定值:<s:property value="http://www.mamicode.com/users.{age}[0]"/> | <s:property value="http://www.mamicode.com/users[0].age"/></li>
		<li>访问Set:<s:property value="http://www.mamicode.com/dogs"/></li>
		<li>访问Set中某个元素:<!--<s:property value="http://www.mamicode.com/dogs[1]"/>--></li>
		<li>访问Map:<s:property value="http://www.mamicode.com/dogMap"/></li>
		<li>访问Map中某个元素:<s:property value="http://www.mamicode.com/dogMap.dog101"/> | <s:property value="http://www.mamicode.com/dogMap[‘dog101‘]"/> | <s:property value="http://www.mamicode.com/dogMap[/"dog101\"]"/></li>
		<li>访问Map中所有的key:<s:property value="http://www.mamicode.com/dogMap.keys"/></li>
		<li>访问Map中所有的value:<s:property value="http://www.mamicode.com/dogMap.values"/></li>
		<li>访问容器的大小:<s:property value="http://www.mamicode.com/dogMap.size()"/> | <s:property value="http://www.mamicode.com/users.size"/> </li>
		<hr />
		
		<%-- 投影:
		1、投影其实就是对集合过滤选择
		2、?表示选取过滤后的所有元素
		3、^表示选取过滤后的第一个元素
		4、$表示选取过滤后的最后一个元素
		 --%>
		<li>投影(过滤):<s:property value="http://www.mamicode.com/users.{?#this.age==1}[0]"/></li>
		<li>投影:<s:property value="http://www.mamicode.com/users.{^#this.age>1}.{age}"/></li>
		<li>投影:<s:property value="http://www.mamicode.com/users.{$#this.age>1}.{age}"/></li>
		<li>投影:<s:property value="http://www.mamicode.com/users.{$#this.age>1}.{age} == null"/></li>
		<hr />
		<li>[]:<s:property value="http://www.mamicode.com/[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

 

结果为:

技术分享

Struts2中OGNL表达式的用法