我一直认为,拦截器是在请求action后,执行action之前所开始。(其实拦截器完全可以在action的执行方法之前,之中,之后任何执行。之后执行只需要将action执行的方法返回的结果取得就可以了,或者可以借助于在拦截器中注册一个监听器。 )那么理论上它是完全可以获得请求的所有参数的。
但是我在拦截器中获得action实例之后:
在通过实例获得action的属性为空,也就是说在这个时候数据并没有注入到action里面。
在网上看到这么一段话,引用下。
[quote]众所周知, Struts2 的 Action 类通过属性可以获得所有相关的值,如请求参数、 Action 配置参数、向其他Action 传送属性值 ( 通过 chain 结果 ) 等等。要获得这些参数值,我们要做的唯一一件事就是在 Action 类中声明与参数同名的属性,在 Struts2 调用 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 类的相应属性。[/quote]
这样看来,我们从两条线看看,一个是封装在http请求中的数据,一个是ValueStack中的数据,他们在什么时候通过请求中的数据进行映射到ValueStack中。答案是在即将执行Action中方法的时候,同时在这个时候进行注入的。
总结下,在实例action后,会创建一个ValueStack(虚拟),然后将action的属性加入到ValueStack中,此时ValueStack还为空,只有属性名称(这也是为什么在拦截器中从ValueStackz中获得不到数据,而通过HTTP请求却可以)。
请求经过拦截器,在拦截器中即将调用Action的方法的时候,HTTP请求中的数据映射到ValueStack中,此时,也完成了类型转换。当然,你也可以在执行之前将HTTP中的数据变更。必须是变更请求中的数据,如果你变更的是ValueStack中的数据,它会将请求中的输入覆盖你变更的数据,因此不会有效果。
但是我在拦截器中获得action实例之后:
TestAction testAction=(TestAction)inter.getAction();
在通过实例获得action的属性为空,也就是说在这个时候数据并没有注入到action里面。
在网上看到这么一段话,引用下。
[quote]众所周知, Struts2 的 Action 类通过属性可以获得所有相关的值,如请求参数、 Action 配置参数、向其他Action 传送属性值 ( 通过 chain 结果 ) 等等。要获得这些参数值,我们要做的唯一一件事就是在 Action 类中声明与参数同名的属性,在 Struts2 调用 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 类的相应属性。[/quote]
这样看来,我们从两条线看看,一个是封装在http请求中的数据,一个是ValueStack中的数据,他们在什么时候通过请求中的数据进行映射到ValueStack中。答案是在即将执行Action中方法的时候,同时在这个时候进行注入的。
总结下,在实例action后,会创建一个ValueStack(虚拟),然后将action的属性加入到ValueStack中,此时ValueStack还为空,只有属性名称(这也是为什么在拦截器中从ValueStackz中获得不到数据,而通过HTTP请求却可以)。
ActionContext ac=actionInvocation.getInvocationContext();
Map<String, Object> str=ac.getParameters();
String[] s=(String[]) str.get("name");
请求经过拦截器,在拦截器中即将调用Action的方法的时候,HTTP请求中的数据映射到ValueStack中,此时,也完成了类型转换。当然,你也可以在执行之前将HTTP中的数据变更。必须是变更请求中的数据,如果你变更的是ValueStack中的数据,它会将请求中的输入覆盖你变更的数据,因此不会有效果。