论坛首页 Java企业应用论坛

Struts2和OGNL

浏览 3585 次
锁定老帖子 主题:Struts2和OGNL
该帖已经被评为隐藏帖
作者 正文
   发表时间:2010-01-13  
        OGNL是XWork引入的一个非常有效的数据处理的工具。我们已经了解了OGNL的基本操作和OGNL的内部结构,接下来,我们来看看XWork对OGNL做了什么样的加强,以及OGNL的体系在Struts2中如何运转。

  1. /**  
  2.  * @author Downpour  
  3.  */  
  4. public class User {   
  5.        
  6.     private Integer id;   
  7.        
  8.     private String name;   
  9.        
  10.     private Department department = new Department();   
  11.        
  12.         // setter and getters   
  13. }   
  14.   
  15. //=========================================================================   
  16.   
  17. /**  
  18.  * @author Downpour  
  19.  */  
  20. public class Department {   
  21.        
  22.     private Integer id;   
  23.        
  24.     private String name;   
  25.            
  26.         // setter and getters   
  27. }   
  28.   
  29. //=========================================================================   
  30.   
  31. <form method="post" action="/struts-example/ognl.action">   
  32.     user name: <input type="text" name="user.name" value="downpour" />   
  33.     department name: <input type="text" name="department.name" value="dev" />   
  34.     <input type="submit" value="submit" />   
  35. </form>   
  36.   
  37. //=========================================================================   
  38.   
  39. /**  
  40.  * @author Downpour  
  41.  */  
  42. public class OgnlAction extends ActionSupport {   
  43.   
  44.     private static final Log logger = LogFactory.getLog(OgnlAction.class);   
  45.   
  46.     private User user;   
  47.        
  48.     private Department department;   
  49.        
  50.     /* (non-Javadoc)  
  51.      * @see com.opensymphony.xwork2.ActionSupport#execute()  
  52.      */  
  53.     @Override  
  54.     public String execute() throws Exception {   
  55.         logger.info("user name:" + user.getName());   // -> downpour   
  56.         logger.info("department name:" + department.getName());   // -> dev   
  57.         return super.execute();   
  58.     }   
  59.   
  60.     // setter and getters   
  61. }   
  62.   
  63. //=========================================================================   
  64.   
  65. user name: <s:property value="user.name" />   
  66. department name: <s:property value="department.name" />   
  67.   
  68. //=========================================================================  
我们可以看到在JSP中,form中的元素input等,都使用OGNL的表达式作为name的值。而在form提交时,这些值都会被设置到Action中的Java对象中。而当Action转向到JSP时,Struts2的Tag又可以从Action的Java对象中,通过OGNL进行取值。

在这里,你看不到任何的OGNL的代码级别操作,因为这些都在Struts2内部进行了封装。而这些封装,都是建立在OGNL的基本概念,也就是根对象和上下文环境之上。下面就分别就这两个方面分别进行讲解。

ValueStack —— 对OGNL的加强

细心的读者可能会发现,在上面的例子中,我们使用了不同的表达式,针对Action中的不同的Java对象进行设值。再结合上一讲我们所例举的OGNL的代码操作示例,我们有强烈的理由怀疑,Struts2在内部有可能执行了这样的操作,才使得页面到Action的设值工作顺利完成:
  1. // "user.name" as OGNL expression, action as OGNL Root object   
  2. Ognl.setValue("user.name", action, "downpour");   
  3. Ognl.setValue("department.name", action, "dev");  

如果这个怀疑是正确的,那么我们就能得出这样一个结论:Struts2的Action是OGNL操作的根对象。

这个结论是我们从现象上推出来的,至于它到底正确与否,我们之后可以通过源码分析来进行验证,在这里先卖一个关子,姑且认为它是正确的。不过这个结论对我们来说非常重要,因为这个结论Struts2的Tag,JSTL和Freemarker等表示层元素获取Action中变量的值打下了坚实的基础。

在Struts2(XWork)中,不仅把Action作为OGNL操作的根对象,作为对OGNL的扩展,它还引入了一个ValueStack的概念。这个概念代表了什么呢?还是让我们看看Struts2的Reference怎么说:

Struts2 Reference 写道
The biggest addition that XWork provides on top of OGNL is the support for the ValueStack. While OGNL operates under the assumption there is only one "root", XWork's ValueStack concept requires there be many "roots".


很明显,ValueStack依照它的结构和作用,至少为我们提供两大特性:

1. ValueStack是一个堆栈结构,堆栈中的每个元素对于OGNL操作来说,都被看作是根对象。

2. 由于ValueStack是一个堆栈结构,所以其中的元素都是有序的,对于某个OGNL表达式来说,OGNL将自堆栈顶部开始查找,并返回第一个符合条件的对象元素。


这里我们有必要对第二点啰嗦几句,举个具体的例子来说(这个例子同样摘自Struts2的Reference):如果在ValueStack中有2个对象,分别是“动物”和“人”,这两个对象都具备一个属性,叫做name,而“动物”还有一个属性叫species,“人”还有个属性叫salary。其中,“动物”对象在ValueStack的栈顶,而“人”这个对象在栈底。那么看看下面的OGNL表达式将返回什么?

  1. species    // call to animal.getSpecies()   
  2. salary     // call to person.getSalary()   
  3. name       // call to animal.getName() because animal is on the top  

对于name这个属性,返回的将是“动物”的name,因为“动物”在栈顶,会被先匹配到OGNL的表达式。但是有的时候,你可能需要访问“人”的name属性,怎么办呢?你可以通过下面的方法:

  1. [0].name   // call to animal.getName()   
  2. [1].name   // call to person.getName()  

Struts2中的OGNL上下文环境

有了ValueStack,我们再来仔细研究一下Struts2中OGNL的上下文环境。

Struts2 Reference 写道
The framework sets the OGNL context to be our ActionContext, and the value stack to be the OGNL root object. (The value stack is a set of several objects, but to OGNL it appears to be a single object.) Along with the value stack, the framework places other objects in the ActionContext, including Maps representing the application, session, and request contexts. These objects coexist in the ActionContext, alongside the value stack (our OGNL root)



也就是说,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对象中的值进行读取。

 

 

   发表时间:2010-01-13  
你这文章抄的,@author Downpour  都没删
0 请登录后投票
   发表时间:2010-01-14  
JArcher 写道
你这文章抄的,@author Downpour  都没删

不好意思,就是Copy,本人仅仅用来分享。
0 请登录后投票
   发表时间:2010-01-14  
看看struts2的源码就知道了,抄也抄得坑坑洼洼的!!
抄人文章应该事先说明.........................................
0 请登录后投票
   发表时间:2010-01-15  
Struts2的性能瓶颈正好恰恰在OGNL上。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics