Struts2 中如何覆盖已内置拦截器的属性(参数)值

在前面一篇 Struts2 中 ModelDriven Action 的 setModel() 为何不起作用? 中发现最漂亮的办法就是修改 ModelDrivern 的 refreshModelBeforeResult 属性为 true,同时留下一个话题。这里接着,即如何覆盖内置拦截器的属性(参数) 值。


如果是自定的拦截器,则可以在 struts.xml 中的 <interceptor> 或 <interceptor-ref> 中用 <param name="paramName">paramValue</param> 来指定参数。但是对于 struts2 核心包内置的或是第三方的拦截器的参数需要进行重新设置该如何呢?

比如在 struts2 包中的 struts-default.xml 中定义很多拦截器,通常我们使用的是其中组织好的 defaultStack 拦截器栈,看 struts-default.xml 中关键几行配置:
 1<struts>
 2    <package name="struts-default" abstract="true">
 3
 4            <interceptor-stack name="defaultStack"><!--引用了18个拦截器-->
 5                <interceptor-ref name="exception"/>
 6                ......
 7                <interceptor-ref name="modelDriven"/>
 8                <interceptor-ref name="fileUpload"/>
 9                <interceptor-ref name="checkbox"/>
10                ......
11            </interceptor-stack>
12       </interceptors>
13
14        <default-interceptor-ref name="defaultStack"/>
15
16    </package>
17</struts>

在我们自己的 struts.xml 中无特别需求的情况下会直接继承 struts-default 配置,也就是使用了 defaultStack 拦截器栈:
1<package name="default" namespace="/" extends="struts-default">

那么我们可以有两种方式来修改 defaultStack 拦截器栈中某个拦截器的参数,还是以修改 defaultStack 栈中的 modelDriven 拦截器的 refreshModelBeforeResult 属性为例。

在 strtus.xml 的每一个 <action> 配置中用 <interceptor-ref name="defaultStack"> 引用默认拦截器栈中修改:
1<action name="hello_unmi">
2    <interceptor-ref name="defaultStack">
3     <param name="modelDriven.refreshModelBeforeResult">true</param>
4 </interceptor-ref>
5 <interceptor-ref name="你自己的拦截器或拦截器栈"...........
6</action>

modelDriven.refreshModelBeforeResult 意义是在 defaultStack 拦截器栈中的 modelDriven 拦截器的 refreshModelBeforeResult 属性,设置为 true。而要是你许多的 Action 有这样的需求,显然一个个的设置是无法接受的,还要知道我们默认的全局拦截器栈就是 defaultStack。

那我们可以采用第二种办法,设置自己的默认拦截器栈,比如 myDefaultStack,那要在 struts.xml 中这么个写法:
 1<package name="default" namespace="/" extends="struts-default">
 2
 3    <interceptors>
 4        <interceptor name="userTracking">
 5            <param name="includeAdmin">true</param> <!--声明时可设置某一属性-->
 6        </interceptor>
 7        <interceptor-stack name="myDefaultStack">
 8            <interceptor-ref name="defaultStack">
 9                <param name="modelDriven.refreshModelBeforeResult">true</param>
10            </interceptor-ref>
11            <interceptor-ref name="userTracking"/>
12                <param name="includeAdmin">false</param> <!-- 定义拦截器栈时可以改属性 -->
13
14            </interceptor-ref>
15        </interceptor-stack>
16    </interceptors>
17
18    <default-interceptor-ref name="myDefaultStack"/>
19
20    ..........................

上面我们看到了多处可以修改拦截器或拦截器栈中的某个拦截器的属性,自然可以用同样的方法来修改自定义拦截器栈中某一拦截器的属性。用 <default-interceptor-ref name="myDefaultStack"/> 定义了新的默认拦截器栈,那么在 default package 中的所有 action 自动应用了这一拦截器栈。如果我们未定义自己的拦截器,而只是想修改 defaultStack 中某个拦截器的属性,只要写成:
 1<package name="default" namespace="/" extends="struts-default">
 2
 3    <interceptors>
 4        <interceptor-stack name="myDefaultStack">
 5            <interceptor-ref name="defaultStack">
 6                <param name="modelDriven.refreshModelBeforeResult">true</param>
 7            </interceptor-ref>
 8        </interceptor-stack>
 9    </interceptors>
10
11    <default-interceptor-ref name="myDefaultStack"/>
12
13    ..........................

此时不知有人会否想像到,如果对于 <default-interceptor-ref> 中能用 <param> 来指定某一属性,岂不更妙,想像一下这样子的:
1<package name="default" namespace="/" extends="struts-default">
2
3    <default-interceptor-ref name="defaultStack"/>
4        <param name="modelDriven.refreshModelBeforeResult">true</param>
5    </default-interceptor-ref>
6
7    ..........................

能的话比起前面是简洁的多,不需要 <interceptor> 相关的声明,但也是只能说想法很美好,可惜 <default-interceptor-ref> 关没有 <param> 子节点的。

参考: 1. Struts中覆盖指定拦截器的参数 永久链接 https://yanbin.blog/struts2-how-to-override-interceptor-parameters/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。