在Struts2 中 ValueStack 的实现(一)

来源:互联网 发布:java接口开发demo下载 编辑:程序博客网 时间:2024/05/23 16:55

1. ValueStack

ValueStack在中文版的《Struts2深入浅出》一书中译作“值栈”。其本身数据结构是一个栈,使用者可以把一些对象(又称作bean)存入值栈中,然后使用动态的表达式来读取bean的属性,或者对bean进行一些其他操作。由于值栈中可能有多个bean,值栈会按bean出栈的顺序依次尝试使用动态的表达式来读取值,直到成功读取值为止。在Struts2中,默认的值栈实现是OgnlValueStack,即默认使用Ognl这个动态表达式语言来读取值。

在Struts2执行一次请求的过程中,Struts2会把当前的Action对象自动放入值栈。这样,在渲染JSP时,JSP里的代码使用<s:property value="..."/>之类标签中的Ognl表达式会直接作用于Action对象,从而方便的读取Action的属性。

如何得到值栈:
  • 在自定义的拦截器中,使用ActionInvocation.getStack()方法( ActionInvocation 是拦截器的方法参数)。
  • 在Action类中,让拦截器注入ValueStack或者使用ActionContext.getContext().getValueStack()来值栈(ActionContext.getContext()为静态方法)。注意:ActionContext分配context的方式是基于线程的,如果使用这种方法,请确保它不会出错。
  • 在JSP中,直接使用标签即可获得值栈里的数据,而一般不用获取值栈本身。
如何将对象存入值栈:
  • Struts2自动存入Action:之前已经提到,Struts2在执行一次请求的过程中会把当前的Action对象自动存入值栈中。
  • ModelDrivenInterceptor会存入Action的model属性:如果你使用了Struts2提供的 ModelDrivenInterceptor,则它会把Action对象的getModel()方法得到的对象存入值栈中。此时,值栈最底层为Action类,其次为这个model。
  • 在自定义的拦截器中存入值栈:得到值栈对象后调用ValueStack.put(Object object)方法。
  • 在Action类中存入值栈:得到值栈对象后调用ValueStack.put(Object object)方法。
  • 在JSP中存入值栈:标签<s:push value="..."></s:push>是专门用来在JSP中把指定的value放入值栈的,但value被放入值栈的时间仅在s:push标签内,即程序运行到</s:push>标签处会把value从值栈中移出。另外,还有一些标签比如<s:iterator/>由于其功能的需要也会把一些对象放到值栈中。
让值栈执行表达式来获得值:
  • 在自定义的拦截器中,获得值栈后,使用ValueStack.findValue(...)等方法。
  • 在Action类中,获得值栈后,使用ValueStack.findVlaue(...)等方法。
  • 在JSP中,一些标签的属性是直接在值栈上执行Ognl表达式的,比如<s:property/>的value属性。如果标签的属性不是直接执行Ognl表达式的,则需要使用“%{}”将表达式括起来,这样Struts2就会以Ognl表达式来执行了。至于到底哪些标签是直接执行Ognl而哪些不是,请参考完整的官方文档。
在JSP中跳过栈顶元素直接访问第二层:
  • 在JSP中,使用[0]、[1]等表达式来指定从栈的第几层开始执行表达式。[0]表示从栈顶开始,[1]表示从栈的第二层开始。比如表达式“name”等价于“[0].name”。参见此处。
在JSP中访问值栈对象本身(而不是它们的属性)
  • 在表示式中使用top关键字来访问对象本身。比如,表达式“name”等价于“top.name”,表达式“[0].top”等价于“top”,表达式“[1].top.name”等价于“[1].name”。

总之,值栈主要目的是为了让JSP内能方便的访问Action的属性。

0 0