1.web app通用的方式,即是:放入sesson,request ,application scope 中
struts是这么作的,绝大多数标签库,框架,都是在这里存放对象供应用程序共享、访问的。在EL中只能访问这些scope变量(如:${anObject})
但这种访问方式(如果不加以封装)有一个弊端:应用程序必需依赖servlet容器的API(tomcat就是common目录下的sevlet.jar),这给应用程序的调试增加了难度。
2.如果对这些对象(request,session...)加以封装,就会极大地方便web应用程序的开发,一般的做法就是将这些scope中的对象放到 map中。webwork就是这么作的,这种封装很普遍(如:Jpetstore也简单地实现了scope的封装),做起来也不难。但作为一个框架,webwork为了能让用户灵活访问这些sope做了个valuestack。action运行中的上下文,以及webwork中所有阶段(action的处理,result的处理,velcity翻译jsp页面)中访问变量都是由valuestack来承担的。
valuestack值栈的含义正如它的名字所表示的那样――对象所组成的栈。OGNL的全称是Object Graph Navigational Language(对象图导航语言),提供了访问值栈中对象的统一方式。它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
值栈中的对象构成及其排列顺序如下所示:
1).临时对象――在执行过程中,临时对象被创建出来并放到了值栈中。举个例子来说,像JSP标签所遍历的对象容器中,当前访问到的值就是临时对象
2).模型对象――如果模型对象正在使用,那么会放在值栈中action的上面
3).Action对象――正在被执行的action
4).固定名称的对象(Named Objects)――这些对象包括有#application, #session, #request, #attr 和 #parameters,以及相应的servlet作用域
访问值栈可以有很多方法,其中最常用的一种就是使用JSP,Velocity或者Freemarker提供的标签。还有就是使用HTML标签访问值栈中对象的属性;结合表达式使用控制标签(例如if,elseif和iterator);使用data标签(set和push)来控制值栈本身。
在使用值栈时,我们无须关心目标对象的作用域。如果要使用名为“name”的属性,直接从值栈中进行查询就可以了。值栈中的每一个元素,都会按照排列顺序依次检查是否拥有该属性。如果有的话,那么就返回对应的值,查询结束。如果没有的话,那么下一个元素就会被访问……直到到达值栈的末尾。这个功能非常强大,我们根本不需要知道所需要的值在什么地方――存在于Action,模型或是HTTP请求中――只要这个值存在,它就会被返回。
但它也有个缺点。如果所请求的是很常见的属性(例如“id”),而你想要从某个特定的对象中(例如action)获取该属性的值,这时候值栈中第一个满足条件的对象返回的属性值就可能不是所想要的结果了。返回结果的确是“id”属性的值,但它可能来自JSP标签,临时对象或者模型对象。这时候就需要用到OGNL来增强值栈的功能了。OSGL并不仅限于访问对象属性,如果我们知道某个action在值栈中的深度,那么就可以用“[2].id”来替换掉 “id”。
实际上OGNL是一套完整的表达式语言。在OGNL里面,可以用“.”来遍历对象图(比如说,使用“person.address”而不是 “getPerson().getAddress()”),它还提供了类型转换,方法调用,集合的操作与生成,集合间的映射,表达式运算和lambda表达式。OGNL的网站上提供了一套完整的指南,地址为http://www.ognl.org/2.6.9/Documentation/html/LanguageGuide/index.html。