标题：OGNL
基本介绍
OGNL是Object-Graph Navigation Language的缩写，它是一种功能强大的表达式语言（Expression Language，简称为EL），通过它简单一致的表达式语法，可以存取对象的任意属性，调用对象的方法，遍历整个对象的结构图，实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
OGNL可以让我们用非常简单的表达式访问对象层，例如，当前环境的根对象为user1，则表达式person.address[0].province可以访问到user1的person属性的第一个address的province属性。
这种功能是模板语言的一个重要补充，象jsp2.0,velocity,jelly等等，都有类似的功能，但是ognl比它们完善得多，而且以一个独立的lib出现，方便我们构建自己的框架。
webwork2和现在的Struts2.x中使用OGNL取代原来的EL来做界面数据绑定，所谓界面数据绑定，也就是把界面元素（例如一个textfield,hidden)和对象层某个类的某个属性绑定在一起，修改和显示自动同步。
和struts1.x的formbean相比，这样做的好处非常明显：在webwork中不需要为每个页面专门写formbean，可以直接利用对象层的对象。例如在对象设计中，我们的User和Person是分开的，而一个注册用户界面需要填写两者的内容，在webwork中，就可以保持后台的对象结构，把属于用户属性的界面元素用user.person.xxx绑定，把属于账号属性的界面元素用user.xxx绑定。
Struts 2
OGNL（Object-Graph Navigation Language），可以方便地操作对象属性的开源表达式语言，使页面更简洁； 
支持运算符（如+-*/），比普通的标志具有更高的自由度和更强的功能； 
Struts 2默认的表达式语言是OGNL，原因是它相对其它表达式语言具有下面几大优势：
支持对象方法调用，如xxx.doSomeSpecial()； 
支持类静态的方法调用和值访问，表达式的格式为@[类全名（包括包路径）]@[方法名 | 值名]，例如：@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME； 
支持赋值操作和表达式串联，如price=100, discount=0.8, calculatePrice(price*discount)，这个表达式会返回80； 
访问OGNL上下文（OGNL context）和ActionContext； 
操作集合对象。
用法
OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用。使用方法如下：
新建名为Struts2_OGNL的Web工程
#”主要有三种用途：
访问OGNL上下文和Action上下文，#相当于ActionContext.getContext()；下表有几个ActionContext中有用的属性： 名称 作用 例子 
parameters 包含当前HTTP请求参数的Map #parametersid[0]作用相当于request.getParameter("id") 
request 包含当前HttpServletRequest的属性（attribute)的Map #request.userName相当于request.getAttribute("userName") 
session 包含当前HttpSession的属性（attribute）的Map #session.userName相当于session.getAttribute("userName") 
application 包含当前应用的ServletContext的属性（attribute）的Map #application.userName相当于application.getAttribute("userName") 
attr 用于按request > session > application顺序访问其属性（attribute） #attr.userName相当于按顺序在以上三个范围（scope）内读取userName属性，直到找到为止 
用于过滤和投影（projecting)集合，如books.{?#this.price<100}； 
构造Map，如#{'foo1':'bar1', 'foo2':'bar2'}。 
下面让我们它们的具体写法，首先是Action类代码：
package tutorial.action;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;
import tutorial.model.Book;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction extends ActionSupport implements ServletRequestAware, SessionAware, ServletContextAware {
private static final long serialVersionUID = 1L;
private HttpServletRequest request;
private Map session;
private ServletContext application;
private List books;
public void setServletRequest(HttpServletRequest request) {
this.request = request; 
}
@SuppressWarnings("unchecked")
public void setSession(Map session) {
this.session = session; 
}
public void setServletContext(ServletContext application) {
this.application = application;
}
public List getBooks() {
return books;
}
@Override
public String execute() {
request.setAttribute("userName", "Max From request");
session.put("userName", "Max From session");
application.setAttribute("userName", "Max From application");
books = new LinkedList();
books.add(new Book("978 0735619678", "Code Complete, Second Edition", 32.99));
books.add(new Book("978 0596007867", "The Art of Project Management", 35.96));
books.add(new Book("978 0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));
books.add(new Book("978 0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));
books.add(new Book("978 0735605350", "Software Estimation: Demystifying the Black Art", 25.19));
return SUCCESS;
}
}
以上代码分别在request、session和application的范围内添加“userName”属性，然后再在JSP页面使用OGNL将其取回。
下面是Ognl.jsp的代码，内容如下：
访问OGNL上下文和Action上下文
parameters.userName:
request.userName: 
session.userName: 
application.userName: 
attr.userName: 
用于过滤和投影（projecting)集合
Books more than $35
<s:iterator value="books.{?#this.price > 35}">
<s:property value="title" /> - $<s:property value="price" /><br>
</s:iterator>
The price of "Code Complete, Second Edition" is: 
构造Map
The value of key "foo1" is 
清单3 WebContent/Ognl.jsp 以上代码值得注意的是“”，因为“books.{?#this.title=='Code Complete, Second Edition'}.{price}”返回的值是集合类型，所以要用“[索引]”来访问其值。 最后是Struts 2的配置文件struts.xml，内容如下： 
/Ognl.jsp
“%”符号的用途是在标志的属性为字符串类型时，计算OGNL表达式的值。
“$”有两个主要的用途，用于在国际化资源文件中，引用OGNL表达式。在Struts 2配置文件
由来
OGNL stands for Object-Graph Navigation Language; it is an expression language for getting and setting properties of Java objects. You use the same expression for both getting and setting the value of a property. 
The ognl.Ognl class contains convenience methods for evaluating OGNL expressions. You can do this in two stages, parsing an expression into an internal form and then using that internal form to either set or get the value of a property; or you can do it in a single stage, and get or set a property using the String form of the expression directly. 
OGNL started out as a way to set up associations between UI components and controllers using property names. As the desire for more complicated associations grew, Drew Davidson created what he called KVCL, for Key-Value Coding Language, egged on by Luke Blanshard. Luke then reimplemented the language using ANTLR, came up with the new name, and, egged on by Drew, filled it out to its current state. Later on Luke again reimplemented the language using JavaCC. Further maintenance on all the code is done by Drew (with spiritual guidance from Luke).
发音
We pronounce OGNL as a word, like the last syllables of a drunken pronunciation of "orthogonal."
表达式
OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型，是将对象的引用值用点串联起来，从左到右，每一次表达式计算返回的结果成为当前对象，后面部分接着在当前对象上进行计算，一直到全部表达式计算完成，返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充，从而使之支持对象树、数组、容器的访问，甚至是类似SQL中的投影选择等操作。 
1. 基本对象树的访问
对象树的访问就是通过使用点号将对象的引用串联起来进行。
例如：xxxx，xxxx.xxxx，xxxx. xxxx. xxxx. xxxx. xxxx　
2. 对容器变量的访问
对容器变量的访问，通过#符号加上表达式进行。
例如：#xxxx，#xxxx. xxxx，#xxxx.xxxxx. xxxx. xxxx. xxxx　
3. 使用操作符号
OGNL表达式中能使用的操作符基本跟Java里的操作符一样，除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外，还能使用 mod, in, not in等。
4. 容器、数组、对象
OGNL支持对数组和ArrayList等容器的顺序访问：例如：group.users[0]
同时，OGNL支持对Map的按键值查找：
例如：#session['mySessionPropKey']
不仅如此，OGNL还支持容器的构造的表达式：
例如：{"green", "red", "blue"}构造一个List，#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}构造一个Map
你也可以通过任意类对象的构造函数进行对象新建：
例如：new Java.net.URL("xxxxxx/")
5. 对静态方法或变量的访问
要引用类的静态方法和字段，他们的表达方式是一样的@class@member或者@class@method(args)：
例如：@com.javaeye.core.Resource@ENABLE，@com.javaeye.core.Resource@getAllResources
6. 方法调用
直接通过类似Java的方法调用方式进行，你甚至可以传递参数：
例如：user.getName()，group.users.size()，group.containsUser(#requestUser)
7. 投影和选择
OGNL支持类似数据库中的投影（projection） 和选择（selection）。
投影就是选出集合中每个元素的相同属性组成新的集合，类似于关系数据库的字段操作。投影操作语法为 collection.{XXX}，其中XXX 是这个集合中每个元素的公共属性。
例如：group.userList.{username}将获得某个group中的所有user的name的列表。
选择就是过滤满足selection 条件的集合元素，类似于关系数据库的纪录操作。选择操作的语法为：collection.{X YYY}，其中X 是一个选择操作符，后面则是选择用的逻辑表达式。而选择操作符有三种：
? 选择满足条件的所有元素
^ 选择满足条件的第一个元素
$ 选择满足条件的最后一个元素
例如：group.userList.{? #txxx.xxx != null}将获得某个group中user的name不为空的user的列表。