struts2 ognl & valueStack

来源:百度文库 编辑:神马文学网 时间:2024/05/05 10:21:27
当访问一个action的时候,此时struts2会把整个action压入valuestack的顶部,此时valuestack就一个action对象。
我们通常会写stack.set(key1,value1)或者statck.setvalue(key2,value2)这两个是有区别的,前者会在valuestack压入一个hashmap,并将key1,value1植入该hashmap那么此时valuestack会有两个对象,顶部是hashmap,底部是action后者会将key2,value2直接植入到顶部的对象,通常是action,假如action没有相应的set方法,那么执行这个方法等于白搭,你假如此时执行valuestack.findvalue就会为空
我们通常会在多个拦截器传递数据,正如前面所说,你必须得再action中写入set方法,否则无效,假如你不想写,那么请用valuestack.set,这样就不用改写action.但又存在一个隐患,假如拦截器1中你写了valuestack.set,然后你在拦截器2中同findvalue获取了该值,这没有问题,假设你忽然想在拦截器2中传一个值给action,问题就暴露了,你会在拦截器2中像平常一样写statck.setvalue,然后在action中加上set,满以为可以传递过去,其实不行,因为此时栈顶是一个map,而非action,你此时是将值植入到map,而非action,所以传值失败。
以上,摘自:http://hi.baidu.com/zist05dz/blog/item/b58dc8b18688655309230291.html
valuestack作为拦截器、action,甚至页面传递数据的一个数据结构,非凡是当栈中存在多个对象的时候,必须注重栈中对象的顺序以免产生一些恼人的问题。
众所周知,Strut 2的Action类通过属性可以获得所有相关的值,如请求参数、Action
配置参数、向其他Action传递属性值(通过chain结果)等等。要获得这些参数值,我
们要做的唯一一件事就是在Action类中声明与参数同名的属性,在Struts 2调用Action
类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值。
要完成这个功能,有很大程度上,Struts 2要依赖于ValueStack对象。这个对象贯
穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当
Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用
Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点
(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的
属性值为null,int类型的属性值为0等。
在处理完上述工作后,Struts 2就会调用拦截器链中的拦截器,当调用完所有的拦
截器后,最后会调用Action类的Action方法,在调用Action方法之前,会将ValueStack
对象顶层节点中的属性值赋给Action类中相应的属性。大家要注意,在这里就给我们带
来了很大的灵活性。也就是说,在Struts 2调用拦截器的过程中,可以改变ValueStack
对象中属性的值,当改变某个属性值后,Action类的相应属性值就会变成在拦截器中最
后改变该属性的这个值。
从上面的描述很容易知道,在Struts 2的的Action类可以获得与属性同名的参数值
就是通过不同的拦截器来处理的,如获得请求参数的拦截器是params,获得Action的配
置参数的拦截器是staticParams等。在这些拦截器内部读取相应的值,并更新
ValueStack对象顶层节点的相应属性的值。而ValueStack对象就象一个传送带,将属性
值从一个拦截器传到了另一个拦截器(当然,在这其间,属性值可能改变),最后会传
到Action对象,并将ValueStack对象中的属性的值终值赋给Action类的相应属性
无意中发现,属性没有写set get 方法,依然会注入值和取到值.
甚是不解,求助于网上依然没有得到解决!
花了点时间看了下源码!
发现:
struts2 参数拦载器在注入值的时候,有两种机制,(调用ognl)
这是OgnlRuntime 类中一段源码 hasSetMethod( context, target, targetClass,
name ) || hasField( context, target, targetClass, name );
他会先查看你的action 中有没有对应的方法,如果发现无此方法,他会利用第二种方法
直接给属性覆值,而无需对应的set方法!(当然都是通过反射机制实现的)
如果action 中属性过多的话,我觉得就不用写set get 方法了!(不知道这个会不会给以
后维护带来问题)
个人总结:OGNL中的值栈相当于一个数据的中转站,或者叫数据的缓冲存储中心。另外,OGNL除了有值栈(VS)这个特别的对象外,它的表达式语言也自成一派。