一、OGNL
OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整个对象的结构图,实现对象属性类型的转换等功能。
2.Struts2的标签库都是使用OGNL表达式来访问ActionContext中的对象数据的。如:<s:propertyvalue="xxx"/>。
3.Struts2将ActionContext设置为OGNL上下文,并将值栈作为OGNL的根对象放置到ActionContext中。
4.值栈(ValueStack) :
1、#的三种用途:
<h3>构造Map</h3>
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
<p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
<p>不使用%:<s:url value="#foobar['foo1']" /></p>
<p>使用%:<s:url value="%{#foobar['foo1']}" /></p>
运行界面如下所示。
he value of key "foo1" is bar1
不使用%:#foobar['foo1']
使用%:bar1
3、$:
(1)在国际化资源文件中,引用OGNL表达式
(2)在Struts 2框架的配置文件中引用OGNL表达式
三、示例
首先创建一个User类、Student类和Teacher类(cn.orlion.model包下):
User类:
package cn.orlion.model; public class User { private String username; private String password; private int age; public User(int age){ this.age = age; } 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString(){ return this.username + ":" + this.age; } }
Teacher类:
package cn.orlion.model; public class Teacher { private String name; private String sex; public Teacher(){ } public Teacher(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
Student类:
package cn.orlion.model; public class Student { // 学生的老师 private Teacher teacher; private String name; private String age; public static String tel = "15000000000"; // 必须提供给struts2一个无参的构造函数 public Student(){ } public Student(String name){ this.name = name; } public String read(){ return "这是student的read()方法"; } public static String eat(){ return "这是student的静态方法eat()"; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
然后struts.xml配置下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.devMode" value="true" /> <constant name="struts.ognl.allowStaticMethodAccess" value="true" ></constant> <package name="ognl" namespace="/" extends="struts-default"> <action name="ognl" class="cn.orlion.actions.OgnlAction"> <result> /ognl.jsp </result> </action> </package> </struts>
创建Action:
package cn.orlion.actions; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.opensymphony.xwork2.ActionSupport; import cn.orlion.model.Student; import cn.orlion.model.Teacher; import cn.orlion.model.User; public class OgnlAction extends ActionSupport{ private Student student; private String username; private String password; private Map<String , Teacher> teachers = new HashMap<String , Teacher>(); private Set<Student> students = new HashSet<Student>(); private List<User> users = new ArrayList<User>(); public String execute() throws Exception{ users.add(new User(1)); users.add(new User(2)); users.add(new User(3)); students.add(new Student("stu1")); students.add(new Student("stu2")); students.add(new Student("stu3")); teachers.put("teh1", new Teacher("teh1")); teachers.put("teh2", new Teacher("teh2")); teachers.put("teh3", new Teacher("teh3")); return SUCCESS; } public String test(){ return "test"; } public Map<String, Teacher> getTeachers() { return teachers; } public void setTeachers(Map<String, Teacher> teachers) { this.teachers = teachers; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } 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; } }
然后ognl.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Ognl Demo</title> </head> <body> 访问值栈中的action的普通属性:username=<s:property value="username" /><br/> <%--访问的是action中的username属性,该属性存在于值栈中 --%> 访问值栈中属性的普通方法,username长度:<s:property value="username.length()" /><br/> <%--打印username字符串长度 --%> 访问值栈中action的普通方法<s:property value="test()" /> <%--调用action中的test()方法的返回值 --%> <hr/> 访问值栈中对象的普通属性(get set方法):student的name=<s:property value="student.name" /><br/> <%--Student必须提供给struts2一个无参的构造函数 --%> <%--打印action中的student的属性的name属性 --%> 访问值栈中对象的普通属性(get set方法):student的teacher的name=<s:property value="student.teacher.name" /><br/> <%--打印action中的student的teacher属性的name属性 --%> 访问值栈中对象的普通方法<s:property value="student.read()" /><br/> <%--调用action中的student的read()方法 --%> <hr/> <p>访问静态属性需要在struts.xml中配置:constant name="struts.ognl.allowStaticMethodAccess" value="true" </p> 访问静态属性<s:property value="@cn.orlion.model.Student@tel" /><br/> <%--调用cn.orlion.model.Student的静态属性tel,格式为 @类@静态属性 --%> 访问静态方法<s:property value="@cn.orlion.model.Student@eat()" /><br/> <%--调用cn.orlion.model.Student的静态方法eat() --%> 访问Math类的静态方法<s:property value="@@max(2 , 3)" /><br/> <%--两个@只能访问Math类 --%> <hr/> 访问普通类的构造方法<s:property value="new cn.orlion.model.User(1)" /><br/> <%--有问题!!!理论由于重写了toString所以会输出null:1--%> <hr/> 访问list<s:property value="users" /><br/> <%--由于重写了toString所以会输出[null:1, null:2, null:3]--%> 访问list中的某个元素<s:property value="users[1]" /><br/> <%--输出null:2--%> 访问list中元素某个属性的集合<s:property value="users.{age}" /><br/> <%--输出[1, 2, 3]--%> 访问list中元素某个属性的集合中的特定值<s:property value="users.{age}[1]" /><br/> <%--输出2--%> 访问set<s:property value="students" /><br/> <%--输出[cn.orlion.model.Student@3aed15c, cn.orlion.model.Student@5d1db1a9, cn.orlion.model.Student@70b2721a]--%> 访问set中某个元素<s:property value="students[1]" /><br/> <%--set无序,取指定下标的值无意义,所以取不到--%> 访问map<s:property value="teachers" /><br/> <%--输出{teh3=cn.orlion.model.Teacher@13d293da, teh1=cn.orlion.model.Teacher@1f1af6a1, teh2=cn.orlion.model.Teacher@683743d6}--%> 访问map中某个元素<s:property value="teachers.teh1" /><br/> <%--输出cn.orlion.model.Teacher@1f1af6a1--%> 访问map中所有key<s:property value="teachers.keys" /><br/> <%--输出[teh3, teh1, teh2]--%> 访问map中所有value<s:property value="teachers.values" /><br/> <%--输出[cn.orlion.model.Teacher@13d293da, cn.orlion.model.Teacher@1f1af6a1, cn.orlion.model.Teacher@683743d6]--%> 访问map的大小<s:property value="teachers.size()" /><br/> <%--输出3--%> 访问list<s:property value="users" /><br/> <hr/> 投影(过滤)<s:property value="users.{?#this.age==1}.{age}" /><br/> <%--取出age=1的User对象的age属性(因为结果不止一个所以是一个集合,所以有中括号) --%> 投影<s:property value="users.{^#this.age>1}.{age}"/><br/> <%--取出age>1的User对象集合的第一个User对象的age属性 --%> 投影<s:property value="users.{$#this.age>1}.{age}"/><br/> <%--取出age>1的User对象集合的最后一个User对象的age属性 --%> 投影<s:property value="users.{$#this.age>1}.{age} == null"/><br/> <%--取出age>1的User对象集合的最后一个User对象的age属性是否是null --%> <hr/> []:<s:property value="[1]" /> <%--访问value stack从第一个至最后一个值,当forward时valuestack会有两个action --%> <%--这里会输出[com.opensymphony.xwork2.DefaultTextProvider@67363fd5] --%> <s:debug></s:debug> </body> </html>
结果:
访问值栈中的action的普通属性:username=rrr
访问值栈中属性的普通方法,username长度:3
访问值栈中action的普通方法test
访问值栈中对象的普通属性(get set方法):student的name=xuesheng
访问值栈中对象的普通属性(get set方法):student的teacher的name=laoshi
访问值栈中对象的普通方法这是student的read()方法
访问静态属性需要在struts.xml中配置:constant name="struts.ognl.allowStaticMethodAccess" value="true"
访问静态属性15000000000
访问静态方法这是student的静态方法eat()
访问Math类的静态方法3
访问普通类的构造方法
访问list[null:1, null:2, null:3]
访问list中的某个元素null:2
访问list中元素某个属性的集合[1, 2, 3]
访问list中元素某个属性的集合中的特定值2
访问set[cn.orlion.model.Student@2712a2e5, cn.orlion.model.Student@6034072c, cn.orlion.model.Student@187b5d94]
访问set中某个元素
访问map{teh3=cn.orlion.model.Teacher@47d7d2f7, teh1=cn.orlion.model.Teacher@5c5e17b0, teh2=cn.orlion.model.Teacher@7ce25307}
访问map中某个元素cn.orlion.model.Teacher@5c5e17b0
访问map中所有key[teh3, teh1, teh2]
访问map中所有value[cn.orlion.model.Teacher@47d7d2f7, cn.orlion.model.Teacher@5c5e17b0, cn.orlion.model.Teacher@7ce25307]
访问map的大小3
访问list[null:1, null:2, null:3]
投影(过滤)[1]
投影[2]
投影[3]
投影false
[]:[com.opensymphony.xwork2.DefaultTextProvider@a715088]
Struts ValueStack Debug
Value Stack Contents
Object | Property Name | Property Value |
---|---|---|
cn.orlion.actions.OgnlAction | container | There is no read method for container |
actionErrors | [] | |
fieldErrors | {} | |
student | cn.orlion.model.Student@30a58f34 | |
students | [cn.orlion.model.Student@2712a2e5, cn.orlion.model.Student@6034072c, cn.orlion.model.Student@187b5d94] | |
locale | zh_CN | |
users | [null:1, null:2, null:3] | |
errorMessages | [] | |
actionMessages | [] | |
password | null | |
texts | null | |
teachers | {teh3=cn.orlion.model.Teacher@47d7d2f7, teh1=cn.orlion.model.Teacher@5c5e17b0, teh2=cn.orlion.model.Teacher@7ce25307} | |
errors | {} | |
username | rrr | |
com.opensymphony.xwork2.DefaultTextProvider | texts | null |