1)预定义拦截器
Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器。由于Struts2的默认拦截器声明和引用都在这个Struts-default.xml里面,因此我们需要到这个文件的struts-default包里去看一下。定义如下:
1 <interceptors> 2 <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> 3 <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> 4 <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> 5 <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> 6 <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> 7 <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/> 8 <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> 9 <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> 10 <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> 11 <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> 12 <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> 13 <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> 14 <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/> 15 <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> 16 <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 17 <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> 18 <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> 19 <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> 20 <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> 21 <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> 22 <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> 23 <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> 24 <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> 25 <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> 26 <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> 27 <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> 28 <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> 29 <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> 30 <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> 31 <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> 32 <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> 33 <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" /> 34 <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" /> 35 <interceptor name="deprecation" class="org.apache.struts2.interceptor.DeprecationInterceptor" /> 36 37 <!-- Basic stack --> 38 <interceptor-stack name="basicStack"> 39 <interceptor-ref name="exception"/> 40 <interceptor-ref name="servletConfig"/> 41 <interceptor-ref name="prepare"/> 42 <interceptor-ref name="checkbox"/> 43 <interceptor-ref name="multiselect"/> 44 <interceptor-ref name="actionMappingParams"/> 45 <interceptor-ref name="params"> 46 <param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param> 47 </interceptor-ref> 48 <interceptor-ref name="conversionError"/> 49 <interceptor-ref name="deprecation"/> 50 </interceptor-stack> 51 52 <!-- Sample validation and workflow stack --> 53 <interceptor-stack name="validationWorkflowStack"> 54 <interceptor-ref name="basicStack"/> 55 <interceptor-ref name="validation"/> 56 <interceptor-ref name="workflow"/> 57 </interceptor-stack> 58 59 <!-- Sample file upload stack --> 60 <interceptor-stack name="fileUploadStack"> 61 <interceptor-ref name="fileUpload"/> 62 <interceptor-ref name="basicStack"/> 63 </interceptor-stack> 64 65 <!-- Sample model-driven stack --> 66 <interceptor-stack name="modelDrivenStack"> 67 <interceptor-ref name="modelDriven"/> 68 <interceptor-ref name="basicStack"/> 69 </interceptor-stack> 70 71 <!-- Sample action chaining stack --> 72 <interceptor-stack name="chainStack"> 73 <interceptor-ref name="chain"/> 74 <interceptor-ref name="basicStack"/> 75 </interceptor-stack> 76 77 <!-- Sample i18n stack --> 78 <interceptor-stack name="i18nStack"> 79 <interceptor-ref name="i18n"/> 80 <interceptor-ref name="basicStack"/> 81 </interceptor-stack> 82 83 <!-- An example of the paramsPrepareParams trick. This stack 84 is exactly the same as the defaultStack, except that it 85 includes one extra interceptor before the prepare interceptor: 86 the params interceptor. 87 88 This is useful for when you wish to apply parameters directly 89 to an object that you wish to load externally (such as a DAO 90 or database or service layer), but can't load that object 91 until at least the ID parameter has been loaded. By loading 92 the parameters twice, you can retrieve the object in the 93 prepare() method, allowing the second params interceptor to 94 apply the values on the object. --> 95 <interceptor-stack name="paramsPrepareParamsStack"> 96 <interceptor-ref name="exception"/> 97 <interceptor-ref name="alias"/> 98 <interceptor-ref name="i18n"/> 99 <interceptor-ref name="checkbox"/> 100 <interceptor-ref name="multiselect"/> 101 <interceptor-ref name="params"> 102 <param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param> 103 </interceptor-ref> 104 <interceptor-ref name="servletConfig"/> 105 <interceptor-ref name="prepare"/> 106 <interceptor-ref name="chain"/> 107 <interceptor-ref name="modelDriven"/> 108 <interceptor-ref name="fileUpload"/> 109 <interceptor-ref name="staticParams"/> 110 <interceptor-ref name="actionMappingParams"/> 111 <interceptor-ref name="params"> 112 <param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param> 113 </interceptor-ref> 114 <interceptor-ref name="conversionError"/> 115 <interceptor-ref name="validation"> 116 <param name="excludeMethods">input,back,cancel,browse</param> 117 </interceptor-ref> 118 <interceptor-ref name="workflow"> 119 <param name="excludeMethods">input,back,cancel,browse</param> 120 </interceptor-ref> 121 </interceptor-stack> 122 123 <!-- A complete stack with all the common interceptors in place. 124 Generally, this stack should be the one you use, though it 125 may do more than you need. Also, the ordering can be 126 switched around (ex: if you wish to have your servlet-related 127 objects applied before prepare() is called, you'd need to move 128 servletConfig interceptor up. 129 130 This stack also excludes from the normal validation and workflow 131 the method names input, back, and cancel. These typically are 132 associated with requests that should not be validated. 133 --> 134 <interceptor-stack name="defaultStack"> 135 <interceptor-ref name="exception"/> 136 <interceptor-ref name="alias"/> 137 <interceptor-ref name="servletConfig"/> 138 <interceptor-ref name="i18n"/> 139 <interceptor-ref name="prepare"/> 140 <interceptor-ref name="chain"/> 141 <interceptor-ref name="scopedModelDriven"/> 142 <interceptor-ref name="modelDriven"/> 143 <interceptor-ref name="fileUpload"/> 144 <interceptor-ref name="checkbox"/> 145 <interceptor-ref name="multiselect"/> 146 <interceptor-ref name="staticParams"/> 147 <interceptor-ref name="actionMappingParams"/> 148 <interceptor-ref name="params"> 149 <param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param> 150 </interceptor-ref> 151 <interceptor-ref name="conversionError"/> 152 <interceptor-ref name="validation"> 153 <param name="excludeMethods">input,back,cancel,browse</param> 154 </interceptor-ref> 155 <interceptor-ref name="workflow"> 156 <param name="excludeMethods">input,back,cancel,browse</param> 157 </interceptor-ref> 158 <interceptor-ref name="debugging"/> 159 <interceptor-ref name="deprecation"/> 160 </interceptor-stack> 161 162 <!-- The completeStack is here for backwards compatibility for 163 applications that still refer to the defaultStack by the 164 old name --> 165 <interceptor-stack name="completeStack"> 166 <interceptor-ref name="defaultStack"/> 167 </interceptor-stack> 168 169 <!-- Sample execute and wait stack. 170 Note: execAndWait should always be the *last* interceptor. --> 171 <interceptor-stack name="executeAndWaitStack"> 172 <interceptor-ref name="execAndWait"> 173 <param name="excludeMethods">input,back,cancel</param> 174 </interceptor-ref> 175 <interceptor-ref name="defaultStack"/> 176 <interceptor-ref name="execAndWait"> 177 <param name="excludeMethods">input,back,cancel</param> 178 </interceptor-ref> 179 </interceptor-stack> 180 181 </interceptors> 182 183 <default-interceptor-ref name="defaultStack"/>
- params拦截器
这个拦截器是必不可少的,因为就是由它偷偷的把请求参数设置到相应的Action的属性去的,并自动进行类型转换。
- staticParams拦截器
将struts.xml配置文件里定义的Action参数,设置到对应的Action实例中,Action参数使用<param>标签,是<action>标签的子元素。struts.xml的示例如下:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <param name="account">test</param> </action>
这要求Action中一定要有一个account的属性,并有相应的getter/setter方法。运行的时候,Action的account属性在初始化过后,会接到这里的赋值“test”。
注意:params拦截器和staticParams拦截器都会为Action的属性赋值,如果碰到了都要赋同一个值呢,比如request里面有account参数,而struts.xml中也有account参数,最终的值是谁?其实是Action初始化过后,就会把struts.xml中配置的数据设置到Action实例中相应的属性上去。然后,把用户请求的数据设置到Action实例中相应的属性上去。很明显最后的值是用户请求中account的数据。
- timer拦截器
该拦截器可以记录ActionInvocation余下部分执行的时间,并做为日志信息记录下来,便于寻找性能瓶颈。也就是说,该拦截器可以记录Action运行的时间。
- logger拦截器
在日志信息中输出要执行的Action信息 ,这样,在调试的时候,就能很快的定位到这个对应的Action了。
2)拦截器配置说明
- <interceptor>元素用来定义一个拦截器,这里仅仅是一个定义,还没有任何一个Action来引用它。里面的name属性作为唯一标志,而class属性就是这个拦截器的实现类。拦截器的实现类都应该是com.opensymphony.xwork2.interceptor.Interceptor这个接口的实现类。
-
<interceptor-stack>定义了一个拦截器栈,这个栈中可以引用其他已经定义好的拦截器。拦截器栈简化了动作类Action在引用拦截器时的操作。
因为大多数动作类Action在引用拦截器的时候都不会仅仅引用一个拦截器,而是引用一组拦截器,而多个动作类Action大概又会引用同一组拦截器,这时候,为了引用的方便,可以把多个拦截器组合成一个拦截器栈。Action在引用的时候,只需要引用这个拦截器栈就可以了,而不是引用每一个拦截器。下面看一下struts-2.1.dtd对于<action>元素的定义:
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
action元素后面出现的interceptor-ref子元素后面用*来修饰,这说明一个action元素可以有不限个数的interceptor-ref子元素。那么在<action>元素中,如何使用<interceptor-ref>子元素呢?其实很简单,只需要在<action>元素中,配置需要的<interceptor-ref>子元素就可以了,<interceptor-ref>子元素里面配置需要使用的拦截器的名称,比如:
<action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction"> <param name="account">test</param> <result>/s2impl/welcome.jsp</result> <interceptor-ref name="staticParams"/> <interceptor-ref name="defaultStack"/> </action>
<interceptor-ref>子元素中的name,不仅仅可以是一个已经定义好的拦截器的名称,还可以是一个已经定义好的拦截器栈的名称。上面的示例,就引用了一个拦截器和一个拦截器栈。
- <default-interceptor-ref>在包上声明包内所有的Action都使用的拦截器
先看一下struts-2.1.dtd对于<package>元素的定义:
<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, default-action-ref?, default-class-ref?, global-results?, global-exception-mappings?, action*)>
其实,在配置自己的package的时候所扩展的struts-default包里面,就已经定义了一个<default-interceptor-ref>,在Struts-default.xml中定义的struts-default包内,有如下定义:
<default-interceptor-ref name="defaultStack"/>
正是因为有这个定义,我们都没有主动去配置拦截器,但实际上,是有拦截器在运行并执行很重要的工作,只不过是使用的默认的拦截器,我们不知道罢了。
3)拦截器的调用顺序
在学习了预定义拦截器的配置使用之后,接下来看看<action>元素引用拦截器的调用顺序。在拿到一个动作类的声明<action>元素后,如何找到它引用的拦截器呢?
1:首先,要找它自己有没有声明拦截器的引用,即<action>元素有没有<interceptor-ref>子元素,如果有,则不用继续再找,直接使用这些拦截器,如果没有,下一步。
2:其次,找这个<action>所在的包有没有声明默认的拦截器引用,即<package>元素的<default-interceptor-ref>子元素, 如果有,则不用继续再找,直接使用这些拦截器,如果没有,下一步。
3:最后,递归地寻找这个包的父包有没有声明默认的拦截器引用,直到找到有拦截器引用就为止。
特别注意:这三个地方的定义是覆盖的关系,什么意思呢?就是如果<action>里面声明了拦截器引用,那么就以它的为准,其他的定义就无效了。也即是<action>里面的拦截器引用声明会覆盖<package>里面的缺省拦截器声明,而<package>里面的缺省拦截器声明又会覆盖父包的<package>里面的缺省拦截器声明,以此类推。
4)全局拦截器的配置
<package name="helloworld" extends="struts-default"> <interceptors> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"/> <action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction"> <result name="toWelcome">/${folder}/welcome.jsp</result> <result name="input">/${folder}/login.jsp</result> </action> </package>
参考资料:http://www.iteye.com/topic/1124526