OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,是一个第三方开源项目。
OGNL本身是与struts2 没有任何关系 ,但struts2框架使用了OGNL用于进行表达式的计算工作。struts2通过使用OGNL简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
OGNL特点:
- 支持对象方法调用
- 可以操作集合对象
- 可以直接创建对象
- 支持类静态方法调用和常量访问,表达式的格式为:
@[全限定性类名]@[方法名|常量名]
如:@java.lang.Integer@parseInt(“123”)或@java.lang.Math@PI
不过静态方法的访问,需要通过在struts2的配置文件struts.xml中设置常量struts.ognl.allowStaticMethodAccess的值为true进行开启。
OGNL以map的形式展现其内部(文档原句:The top level object dealing with OGNL is a Map (usually referred as a context map or context))
在action中直接获取context及内部的值很麻烦,所以给了context另一个定义,即ActionContext。可以通过ActionContext简单获取。(servletApi值也是存在这里,所以获取的也是这里面的,所以ActionContext.getContext获取的不是真正的request)
ValueStack vs = ActionContext.getContext().getValueStack();//获取值栈
OGNL中的值栈是核心,对其操作方式有如下:(对值栈操作实质上是对其中的root进行操作)
//向值栈中加入无名对象,实际是放到它的root属性中
Student st= new Student("zhangsan",21);
vs.push(st);
//向值栈直接放入有名对象,实际是放到它的root属性中
Student st1 = new Student("lisi",20);
Map<String, Student> map = new HashMap<String,Student>();
map.put("st1", st1);
vs.push(map);
Student st2 = new Student("lisi",21);
vs.set("st2", st2);
//将root作为ArrayList放入数据
Student st3 = new Student("wisi",21);
vs.getRoot().add(st3);
System.out.println((Student)vs.getRoot().get(5));
通过如下可在页面显示及查看值栈内容:
<%@ 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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
name = <s:property value="name"/><br>
age = <s:property value="age"/><br>
st2.name = <s:property value="st2.name"/><br>
st2age = <s:property value="st2.age"/>
</body>
</html>
root的实质是ArrayList,所以里面存的对象都是无名对象,只能通过对象的属性来获取相应值
context中数据加载顺序:
当在Action中仅向context中放入某数据lov后,页面无论是通过#从context读取,还是不用#向root读取,都能读到(后者先去root找相关数据,没有就在context下找)
String lov = "lov";
ActionContext.getContext().put("lov", lov);
lov = <s:property value="lov"/><br>
#lov = <s:property value="#lov"/><br>
当通过表单发出请求时,表单值传到context.map下的request中,获取其中的值时
# request.name底层执行的是request.getAttribute();
request.getAttribute();被struts2包装后的查找顺序是:
request域空间->root->context
通过request = <%=request %>可以得出,这里的request不是原始的request了:
以下为页面中的一些OGNL操作(list,map遍历,条件判断,查询)
<!-- set标签定义的对象均存放于context中 -->
<!-- list -->
<s:set var="list" value="{'1','2','3'}"></s:set>
<s:iterator value="list"> <!-- iterator表情默认会将当前的迭代对象放入值栈栈顶 -->
<s:property/><br> <!-- property标签默认输出值栈栈顶元素 -->
</s:iterator>
<br>
<!-- map -->
<s:set var="map" value="#{'one':'1','two':'2' }"></s:set>
<s:iterator value="#map">
<s:property/><br>
</s:iterator>
<s:iterator value="#map" var="entry">
<s:property value="entry"/><br>
</s:iterator>
<s:iterator value="#map">
<s:property value="key"/>=<s:property value="value"/><br>
</s:iterator>
<!-- 集合元素判断-->
<s:property value="'1' in #map"/>
<s:property value="'1' not in #map"/>
<!-- 集合投影 -->
<s:bean name="com.test.Student" var="st1" >
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="12"></s:param>
</s:bean>
<s:bean name="com.test.Student" var="st2">
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="13"></s:param>
</s:bean>
<s:bean name="com.test.Student" var="st3">
<s:param name="name" value="'lov'"></s:param>
<s:param name="age" value="13"></s:param>
</s:bean>
<s:set var="students" value="{#st1,#st2,#st3}"></s:set>
<s:set var="studentsName" value="#students.{name}"></s:set>
<s:iterator value="#students">
<s:property/><br>
</s:iterator>
<s:iterator value="#studentsName">
<s:property/><br>
</s:iterator>
<!-- 集合查询 -->
<s:iterator value="#students.{^#this.age>11}">
<s:property/><br>
</s:iterator>
<s:iterator value="#students.{$#this.age>11}">
<s:property/><br>
</s:iterator>