ValueStack 与 OGNL

ValueStack 与 OGNL

值栈的含义正如它的名字所表示的那样——对象所组成的栈。OGNL的全称是Object Graph Navigational Language(对象图导航语言),提供了访问值栈中对象的统一方式。
值栈中的对象构成及其排列顺序如下所示:
1. 临时对象——在执行过程中,临时对象被创建出来并放到了值栈中。举个例子来说,像JSP标签所遍历的对象容器中,当前访问到的值就是临时对象
2. 模型对象——如果模型对象正在使用,那么会放在值栈中action的上面
3. Action对象——正在被执行的action
4. 上下文中固定名称的对象(Named Objects)——这些对象包括有#application, #session, #request, #attr 和 #parameters,以及相应的servlet作用域

 

struts2中的OGNL上下文
struts2对OGNL上下文的概念又做了进一步扩充,在struts2中,OGNL上下文通常如下所示: 
  
                             |--request  
                             |  
                             |--application  
                             |   
      context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]  
                             |  
                             |--session  
                             |  
                             |--attr  
                             |  
                             |--parameters

 

代码示例

public interface User {   
    public String getName();   
    public Date getRegisterDate();   
    public Customer getCustomer();   
}   
public interface Customer {   
    public String getId();   
    public String getName();   
    public boolean isVip();   
}   
public interface EntCustomer extends Customer {   
    public String getTrustId(); // 组织机构代码证号   
} 

那么在上面的环境中,我们可以有如下的OGNL表达式:
Java代码
#user.name // 取用户的姓名  
#user.age // 取用户年龄  
#user.birthday // 取用户生日  
#user.customer.name // 取用户所属客户的名称  
#request.parameters // 取请求参数 
请注意上面表达式中的"#user"和"#request"的用法,"#"表示访问环境/上下文中的对象。

现在可以很方便地访问环境中的对象了,那么如果你比较懒惰的话(记住:在程序员群体,懒惰是褒义词!),你是否觉得访问用户的姓名,年龄,生日,等等其它属性如果全部要使用"#user"来访问会不会太麻烦了呢?OK,ONGL的设计者早就考虑了这个问题,我们可以指定user为环境中的特权对象,访问该对象可以不需要使用#user的方式,如下所示代码与上面的完全等价,当然,前提是要预先指定user为特权对象:


name // 取用户的姓名  
age // 取用户年龄  
birthday // 取用户生日  
customer.name // 取用户所属客户的名称  
#request.parameters // 取请求参数 
我们上面所说的"特权对象"在OGNL中称为"根对象"(root)

 

我们可以使用"#requet"访问HttpServletRequest对象, "#session"访问HttpSession对象,但请注意"根对象"是什么?是ValueStack!
那么ValueStack是什么?值栈。也就是一组对象的堆栈。也就是说,在struts2中,根对象不是我们通常的一个对象,而是一组对象。我们可以push新的对象到值栈中,也可以弹出值栈的栈顶对象。如上图所示,假设我们将user对象push到值栈中,那么如下的表达式将与之前我们见过的表达式一样,具有相同的结果.


也就是说,我们使用name这个表达式的时候,ONGL会取"根对象"的name属性,但现在根对象是ValueStack!那么访问ValueStack的name属性意味着什么呢?这意味着: ValueStack会先查看栈顶元素是否有name属性,如果有就返回该属性值,否则取出栈顶下的元素,继续查看,直到栈底为止。

 

其实,我们可以ValueStack vs = (ValueStack)request.getAttribute("struts.valueStack");直接去访问.

//获取封装输出信息的ValueStack对象
ValueStack vs = (ValueStack)request.getAttribute("struts.valueStack");
//调用ValueStack的fineValue方法获取Action中的books属性值
String[] books = (String[])vs.findValue("books");
<%@taglib prefix="s" uri="/struts-tags"%>
通过s:iterator迭代出value
		<table border="1" width="360">
			<caption>
				作者李刚的图书
			</caption>
			<!-- 迭代输出ValueStack中的books对象,其中status是迭代的序号 -->
			<s:iterator value="books" status="index">
			    
				<!-- 判断序号是否为奇数 -->
				<s:if test="#index.odd == true">
					<tr style="background-color: #cccccc">
				</s:if>
				<!-- 判断迭代元素的序号是否不为偶数 -->
				<s:else>
					<tr>
				</s:else>
				<td>
					书名:
				</td>
				<td>
					<s:property />
				</td>
				</tr>
			</s:iterator>
		</table>

 

你可能感兴趣的:(jsp,servlet,struts,360)