Struts2和OGNL
??????? OGNL是XWork引入的一个非常有效的数据处理的工具。我们已经了解了OGNL的基本操作和OGNL的内部结构,接下来,我们来看看XWork对OGNL做了什么样的加强,以及OGNL的体系在Struts2中如何运转。
- /** ? ?*?@author?Downpour ? ?*/?? public?class?User?{ ?? ???? ?? ????private?Integer?id; ?? ???? ?? ????private?String?name; ?? ???? ?? ????private?Department?department?=?new?Department(); ?? ???? ?? ????????//?setter?and?getters ?? } ?? ?? //========================================================================= ?? ?? /** ? ?*?@author?Downpour ? ?*/?? public?class?Department?{ ?? ???? ?? ????private?Integer?id; ?? ???? ?? ????private?String?name; ?? ???????? ?? ????????//?setter?and?getters ?? } ?? ?? //========================================================================= ?? ?? <form?method="post"?action="/struts-example/ognl.action"> ?? ????user?name:?<input?type="text"?name="user.name"?value="downpour"?/> ?? ????department?name:?<input?type="text"?name="department.name"?value="dev"?/> ?? ????<input?type="submit"?value="submit"?/> ?? </form> ?? ?? //========================================================================= ?? ?? /** ? ?*?@author?Downpour ? ?*/?? public?class?OgnlAction?extends?ActionSupport?{ ?? ?? ????private?static?final?Log?logger?=?LogFactory.getLog(OgnlAction.class); ?? ?? ????private?User?user; ?? ???? ?? ????private?Department?department; ?? ???? ?? ????/*?(non-Javadoc) ? ?????*?@see?com.opensymphony.xwork2.ActionSupport#execute() ? ?????*/?? ????@Override?? ????public?String?execute()?throws?Exception?{ ?? ????????logger.info("user?name:"?+?user.getName());???//?->?downpour ?? ????????logger.info("department?name:"?+?department.getName());???//?->?dev ?? ????????return?super.execute(); ?? ????} ?? ?? ????//?setter?and?getters ?? } ?? ?? //========================================================================= ?? ?? user?name:?<s:property?value="user.name"?/> ?? department?name:?<s:property?value="department.name"?/> ?? ?? //=========================================================================??
在这里,你看不到任何的OGNL的代码级别操作,因为这些都在Struts2内部进行了封装。而这些封装,都是建立在OGNL的基本概念,也就是根对象和上下文环境之上。下面就分别就这两个方面分别进行讲解。
ValueStack —— 对OGNL的加强
细心的读者可能会发现,在上面的例子中,我们使用了不同的表达式,针对Action中的不同的Java对象进行设值。再结合上一讲我们所例举的OGNL的代码操作示例,我们有强烈的理由怀疑,Struts2在内部有可能执行了这样的操作,才使得页面到Action的设值工作顺利完成:
- //?"user.name"?as?OGNL?expression,?action?as?OGNL?Root?object ?? Ognl.setValue("user.name",?action,?"downpour"); ?? Ognl.setValue("department.name",?action,?"dev");??
如果这个怀疑是正确的,那么我们就能得出这样一个结论:Struts2的Action是OGNL操作的根对象。
这个结论是我们从现象上推出来的,至于它到底正确与否,我们之后可以通过源码分析来进行验证,在这里先卖一个关子,姑且认为它是正确的。不过这个结论对我们来说非常重要,因为这个结论Struts2的Tag,JSTL和Freemarker等表示层元素获取Action中变量的值打下了坚实的基础。
在Struts2(XWork)中,不仅把Action作为OGNL操作的根对象,作为对OGNL的扩展,它还引入了一个ValueStack的概念。这个概念代表了什么呢?还是让我们看看Struts2的Reference怎么说:
很明显,ValueStack依照它的结构和作用,至少为我们提供两大特性:
1. ValueStack是一个堆栈结构,堆栈中的每个元素对于OGNL操作来说,都被看作是根对象。
2. 由于ValueStack是一个堆栈结构,所以其中的元素都是有序的,对于某个OGNL表达式来说,OGNL将自堆栈顶部开始查找,并返回第一个符合条件的对象元素。
这里我们有必要对第二点嗦几句,举个具体的例子来说(这个例子同样摘自Struts2的Reference):如果在ValueStack中有2个对象,分别是“动物”和“人”,这两个对象都具备一个属性,叫做name,而“动物”还有一个属性叫species,“人”还有个属性叫salary。其中,“动物”对象在ValueStack的栈顶,而“人”这个对象在栈底。那么看看下面的OGNL表达式将返回什么?
- species????//?call?to?animal.getSpecies() ?? salary?????//?call?to?person.getSalary() ?? name???????//?call?to?animal.getName()?because?animal?is?on?the?top??
对于name这个属性,返回的将是“动物”的name,因为“动物”在栈顶,会被先匹配到OGNL的表达式。但是有的时候,你可能需要访问“人”的name属性,怎么办呢?你可以通过下面的方法:
- [0].name???//?call?to?animal.getName() ?? [1].name???//?call?to?person.getName()??
Struts2中的OGNL上下文环境
有了ValueStack,我们再来仔细研究一下Struts2中OGNL的上下文环境。
也就是说,ActionContext是Struts2中OGNL的上下文环境。它维护着一个Map的结构,下面是这个结构的图示:
其中,ValueStack是这个上下文环境中的根对象,而除了这个根对象以外,Struts2还在这个上下文环境中放了许多额外的变量,而这些变量多数都是被XWork封装过的Servlet对象,例如request,session,servletContext(application)等,这些对象都被封装成Map对象,随着ActionContext作用于整个Action执行的生命周期中。
在这里,或许有些读者会提出问题来,为什么好好的Servlet对象要在这里被封装成Map对象呢?我想原因可能有以下两个:
1. 对Struts2的Action彻底屏蔽Servlet容器,从而无需再使用底层Servlet API进行编程。你所面对的,将永远是一个又一个的Java对象。
2. 便于各种View技术,例如JSP,Freemarker,Velocity等对ValueStack中上下文环境,尤其是Servlet对象中的数据进行读取。试想,如果在这里不将HttpServletRequest,HttpSession等Servlet对象转化成Map,那么我们将很难通过OGNL表达式,对这些Servlet对象中的值进行读取。
?
?
1 楼 JArcher 2010-01-13 你这文章抄的,@author Downpour 都没删 2 楼 longgangbai 2010-01-14 JArcher 写道你这文章抄的,@author Downpour 都没删不好意思,就是Copy,本人仅仅用来分享。 3 楼 kjj 2010-01-14 看看struts2的源码就知道了,抄也抄得坑坑洼洼的!!
抄人文章应该事先说明......................................... 4 楼 jansel 2010-01-15 Struts2的性能瓶颈正好恰恰在OGNL上。