我自定义了一个拦截器,目的是在action执行之前像ValueStack中设置一些属性,代码是这样的:
- HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST);
-
OgnlValueStack stack=(OgnlValueStack)request.getAttribute("struts.valueStack");
-
-
-
-
-
List<Category> cityList=systemService.getCategorySortList("city");
-
stack.set("cityList",cityList);
-
-
EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu");
-
List<FrontMenu> frontMenuList=(List)proxy.get(FrontMenu.class,
"frontmenus", "menus.xml");
-
stack.set("frontMenuList",frontMenuList);
-
-
return invocation.invoke();
HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST); OgnlValueStack stack=(OgnlValueStack)request.getAttribute("struts.valueStack"); /** * Set the properties */ List<Category>
cityList=systemService.getCategorySortList("city"); stack.set("cityList",cityList); EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu"); List<FrontMenu> frontMenuList=(List)proxy.get(FrontMenu.class, "frontmenus", "menus.xml");
stack.set("frontMenuList",frontMenuList); return invocation.invoke();
struts.xml中是这样配置的:
<!--引用默认拦截器-->
<interceptor-ref name="properties" />
<interceptor-ref name="defaultStack" />
这样配置以后确实可以达到我要的效果,但是问题却出来了,这样配置以后表单参数无法获得,全都是默认为空。我们来看下面一段描述:
众所周知,
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 类的相应属性。
从上面的描述可以看出,当在拦截器中进行ValueStack传递的时候,属性值是可能改变,分析原因我们大概可以知道是这段代码:
-
-
-
-
List<Category> cityList=systemService.getCategorySortList("city");
-
stack.set("cityList",cityList);
-
-
EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu");
-
List<FrontMenu> frontMenuList=(List)proxy.get(FrontMenu.class,
"frontmenus", "menus.xml");
-
stack.set("frontMenuList",frontMenuList);
/** * Set the properties */ List<Category> cityList=systemService.getCategorySortList("city"); stack.set("cityList",cityList); EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu"); List<FrontMenu>
frontMenuList=(List)proxy.get(FrontMenu.class, "frontmenus", "menus.xml"); stack.set("frontMenuList",frontMenuList);
影响了后续defaultStack对属性值的设置,所以我们应该将这段代码最后执行,那么怎么最后执行了,这里就要知道拦截器栈的执行顺序的知识了,在这里就不讲了,修改后是遮掩的:
- HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST);
-
OgnlValueStack stack=(OgnlValueStack)request.getAttribute("struts.valueStack");
-
- String result=invocation.invoke();
-
-
-
-
-
List<Category> cityList=systemService.getCategorySortList("city");
-
stack.set("cityList",cityList);
-
-
EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu");
-
List<FrontMenu> frontMenuList=(List)proxy.get(FrontMenu.class,
"frontmenus", "menus.xml");
-
stack.set("frontMenuList",frontMenuList);
-
-
return result;
HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST); OgnlValueStack stack=(OgnlValueStack)request.getAttribute("struts.valueStack"); String result=invocation.invoke(); /** *
Set the properties */ List<Category> cityList=systemService.getCategorySortList("city"); stack.set("cityList",cityList); EhcacheVindicatorProxy proxy=new EhcacheVindicatorProxy("menu"); List<FrontMenu> frontMenuList=(List)proxy.get(FrontMenu.class,
"frontmenus", "menus.xml"); stack.set("frontMenuList",frontMenuList); return result;
这样就可以保证不会干扰params之类的默认拦截器的执行。
这里要注意的是拦截器的执行顺序,如果设成这样:
- <!--引用默认拦截器-->
-
<interceptor-ref name="defaultStack" />
-
<interceptor-ref name="properties" />
-
<!--引用默认拦截器--><interceptor-ref name="defaultStack" /><interceptor-ref name="properties" />
我们要设的值不会设置成功
当然在这里具体的原因我没有分析,只大略讲了一下