本文為本人翻譯struts2的官方網站上的關于攔截器的說明文檔,官方網站上的說明均是英文的,不方便熱愛學習而英語又不太好的朋友。該說明文檔地址是http://struts.apache.org/2.0.11/docs/interceptors.html。
許多的Struts2中的Action需要共享一些共用信息或者是模塊,有些Action需要對輸入進行驗證,另外一些Action或許需要對文件上傳之前做一些邏輯處理,又或者一些Action需要對重復提交進行保護,還有一些Actiion需要在頁面顯示前,初始化下拉框或一些頁面組件。
Struts2框架使用了Interceptor(攔截器)策略使共享這些關心的模塊更簡單的使用起來。當需要使用到一些映射到Action的資源時,框架生成了Action對象,但在該Action被執行前,執法該Action中的方法被另外一個對象攔截了,在Action執行時,可能再次被攔截,我們親切地稱此對象為攔截器。
理解攔截器
攔截器能夠在一個Action執行前后攔截它。目前的很多框架的核心實現均是基于攔截器。(本人說兩句,OOP因為攔截器而顯得更為精彩,AOP必將成為下一個核心關注點)。攔截器可以幫助實現很多公共的內容,其中有重復提交,類型轉換,對象初始化,驗證,文件上傳,頁面初始化等等。由于每個攔截器都可以像熱插拔的模塊,你可以在你的Action中正確地去使用需要的攔截器。
攔截器可以配置在一個基類的action中,自定義的攔截器可以盡量少或者配合框架中的已有的攔截器。
所以套用句外國人的話說吧,在一個Action執行時,讓我們為它再提升一些吧,給Action更大
的舞臺更強大的力量吧。
如上圖所示,Struts2的Action被一個或者多個攔截器圍繞,所有的用戶請求都會被攔截器 所攔截,最后交給Action處理,處理結果以邏輯視圖的方式返回給用戶,調用的流程由配置文件來實現。
在一些例子中,一個攔截器可以解決像重復提交以及驗證失敗這樣的例子。當然也可以改變一個Action在執行前的狀態。
攔截器可以定義為一個指定執行順序的鏈中,在某些情況下,攔截器的順序非常的重要。
看看上面的配置如果不明白的話,再去看看struts-default.xml可以弄清楚這些攔截器都干什么了。
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />
<bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="tiger" class="com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="notiger" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="struts" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/>
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" class="org.apache.struts2.dispatcher.mapper.DefaultActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="composite" class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful" class="org.apache.struts2.dispatcher.mapper.RestfulActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful2" class="org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true"/>
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true" />
<bean type="org.apache.struts2.views.TagLibrary" name="s" class="org.apache.struts2.views.DefaultTagLibrary" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="struts" optional="true"/>
<bean class="org.apache.struts2.views.velocity.VelocityManager" name="struts" optional="true" />
<bean class="org.apache.struts2.components.template.TemplateEngineManager" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="ftl" class="org.apache.struts2.components.template.FreemarkerTemplateEngine" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="vm" class="org.apache.struts2.components.template.VelocityTemplateEngine" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="jsp" class="org.apache.struts2.components.template.JspTemplateEngine" />
<bean type="com.opensymphony.xwork2.util.XWorkConverter" name="xwork1" class="com.opensymphony.xwork2.util.XWorkConverter" />
<bean type="com.opensymphony.xwork2.util.XWorkConverter" name="struts" class="com.opensymphony.xwork2.util.AnnotationXWorkConverter" />
<bean type="com.opensymphony.xwork2.TextProvider" name="xwork1" class="com.opensymphony.xwork2.TextProviderSupport" />
<bean type="com.opensymphony.xwork2.TextProvider" name="struts" class="com.opensymphony.xwork2.TextProviderSupport" />
<bean type="org.apache.struts2.components.UrlRenderer" name="struts" class="org.apache.struts2.components.ServletUrlRenderer"/>
<!-- Only have static injections -->
<bean class="com.opensymphony.xwork2.ObjectFactory" static="true" />
<bean class="com.opensymphony.xwork2.util.XWorkConverter" static="true" />
<bean class="com.opensymphony.xwork2.util.OgnlValueStack" static="true" />
<bean class="org.apache.struts2.dispatcher.Dispatcher" static="true" />
<bean class="org.apache.struts2.components.Include" static="true" />
<bean class="org.apache.struts2.dispatcher.FilterDispatcher" static="true" />
<bean class="org.apache.struts2.views.util.ContextUtil" static="true" />
<bean class="org.apache.struts2.views.util.UrlHelper" static="true" />
<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>
<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
<!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample JSON validation stack -->
<interceptor-stack name="jsonValidationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack">
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample i18n stack -->
<interceptor-stack name="i18nStack">
<interceptor-ref name="i18n"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- An example of the params-prepare-params trick. This stack
is exactly the same as the defaultStack, except that it
includes one extra interceptor before the prepare interceptor:
the params interceptor.
This is useful for when you wish to apply parameters directly
to an object that you wish to load externally (such as a DAO
or database or service layer), but can't load that object
until at least the ID parameter has been loaded. By loading
the parameters twice, you can retrieve the object in the
prepare() method, allowing the second params interceptor to
apply the values on the object. -->
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
<!-- A complete stack with all the common interceptors in place.
Generally, this stack should be the one you use, though it
may do more than you need. Also, the ordering can be
switched around (ex: if you wish to have your servlet-related
objects applied before prepare() is called, you'd need to move
servlet-config interceptor up.
This stack also excludes from the normal validation and workflow
the method names input, back, and cancel. These typically are
associated with requests that should not be validated.
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
<!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
</package>
</struts>
看看上面的struts-default.xml中的默認配置,都已經事先定義了若干個攔截器使用。
攔截器的類已經定義在特殊的配置文件中,這個配置文件的名字就叫做struts-default.xml,如果你繼承了struts-default默認的包名,那你就可以使用這些攔截器了,否則你必須在你自己的包中定義攔截器在<interceptors>中進行定義。
個人理解
在struts.xml配置文件中,如果要定義攔截器,需要為攔截器類指定一個攔截器名。定義以<interceptor../>元素來實現。還可以定義<param../>參數子元素,用來對攔截器的參數初始化。當然除了可以定義攔截器還可以定義攔截器棧,我也把它稱之為攔截器鏈。攔截器棧由多個攔截器 組成的一個攔截器鏈。定義攔截器鏈使用<interceptor-stack../>元素,當然在這個元素中還需要定義大量的<interceptor-ref ../>,即該攔截器鏈所包含的攔截器引用。在攔截器鏈定義的<interceptor-ref.../>元素中,其name除了可以是一個攔截器的名稱,也可以是一個其它的攔截器鏈。攔截器鏈與攔截器在本質上并無區別,目的都是為了進行攔截。大家可以去看看struts-default.xml配置文件,其中定義了很多攔截器以及攔截器鏈。其中有一個定義為<default-interceptor-ref name="defaultStack"/>意思是定義了一個默認的攔截器鏈,只要是繼承了struts-default包的包均有該默認的攔截器,當然你也可以定義自己的默認的攔截器鏈。<package name="***" extends ="struts-default">該元素的意思是定義了一個繼承于struts-default包的包,那么該包中的所有action均可使用struts-default.xml中定義的攔截器以及攔截器鏈。其中注意一點,struts-default.xml中定義了一系列的攔截器和攔截器鏈,同時也定義了一個默認的攔截器defaultStack,一電定義了默認的攔截器,那么該攔截器將會對包中的所有的Action起作用,當然如果你的Action中顯式地定義了攔截器,那么默認攔截器將會失去作用,當然如果想不讓他失去作用,那么也必須顯式地定義系統默認的攔截器。
<default-interceptor-ref ..../>元素為<package../>元素的一個子元素配置,如果在某個包中定義了一個默認的攔截器,那么此攔截器將對該包中的所有的Action都是有效的,當然一定要記住,顯式地定義攔截器的情況除外。
當然除了可以使用系統提供的默認的攔截器,我們也可以自定義自己的攔截器。Struts2框架提供了一個定義攔截器的接口Interceptor接口。同時Struts2框架也提供了一個可以用于過濾攔截Action方法的類MethodFilterInterceptor。該類有兩個屬性excludeMethods和includeMethods。分別代表指定攔截器拒絕攔截的方法和需要攔截的方法。例:
<package name="struts2tutoial" extends="struts-default">
<interceptors>
<interceptor name="MyInterceptor" class="interceptor.MyInterceptor"/>
<interceptor name="FilterInterceptor" class="interceptor.FilterInterceptor"/>
</interceptors>
<action name="HelloWorld" class="helloWorld">
<result>/helloWorld.jsp</result>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="MyInterceptor"/>
<interceptor-ref name="FilterInterceptor">
<param name="includeMethods">***</param>
<param name="excludeMethods">***</param>
</interceptor-ref>
</action>
</package>
可以看到<param../>元素在此處發揮了作用,自定義的FilterInterceptor起到了過濾方法的作用。
歡迎網友參與討論交流!
許多的Struts2中的Action需要共享一些共用信息或者是模塊,有些Action需要對輸入進行驗證,另外一些Action或許需要對文件上傳之前做一些邏輯處理,又或者一些Action需要對重復提交進行保護,還有一些Actiion需要在頁面顯示前,初始化下拉框或一些頁面組件。
Struts2框架使用了Interceptor(攔截器)策略使共享這些關心的模塊更簡單的使用起來。當需要使用到一些映射到Action的資源時,框架生成了Action對象,但在該Action被執行前,執法該Action中的方法被另外一個對象攔截了,在Action執行時,可能再次被攔截,我們親切地稱此對象為攔截器。
理解攔截器
攔截器能夠在一個Action執行前后攔截它。目前的很多框架的核心實現均是基于攔截器。(本人說兩句,OOP因為攔截器而顯得更為精彩,AOP必將成為下一個核心關注點)。攔截器可以幫助實現很多公共的內容,其中有重復提交,類型轉換,對象初始化,驗證,文件上傳,頁面初始化等等。由于每個攔截器都可以像熱插拔的模塊,你可以在你的Action中正確地去使用需要的攔截器。
攔截器可以配置在一個基類的action中,自定義的攔截器可以盡量少或者配合框架中的已有的攔截器。
所以套用句外國人的話說吧,在一個Action執行時,讓我們為它再提升一些吧,給Action更大

如上圖所示,Struts2的Action被一個或者多個攔截器圍繞,所有的用戶請求都會被攔截器 所攔截,最后交給Action處理,處理結果以邏輯視圖的方式返回給用戶,調用的流程由配置文件來實現。
在一些例子中,一個攔截器可以解決像重復提交以及驗證失敗這樣的例子。當然也可以改變一個Action在執行前的狀態。
攔截器可以定義為一個指定執行順序的鏈中,在某些情況下,攔截器的順序非常的重要。
struts.xml
<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> </interceptors> <action name="login" class="tutorial.Login"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result> </action> </package>在大部分的Web應用中,我們發現會一再地重復應用一些攔截器的設置。重復地定義一系列的攔截器是個麻煩的事,當然我們可以綁定這些攔截器到一個鏈中。
struts.xml
<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> </interceptor-stack> </interceptors> <action name="login" class="tutuorial.Login"> <interceptor-ref name="myStack"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result> </action> </package>
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />
<bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="tiger" class="com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="notiger" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/>
<bean type="com.opensymphony.xwork2.util.ObjectTypeDeterminer" name="struts" class="com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"/>
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" class="org.apache.struts2.dispatcher.mapper.DefaultActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="composite" class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful" class="org.apache.struts2.dispatcher.mapper.RestfulActionMapper" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="restful2" class="org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true"/>
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" optional="true" />
<bean type="org.apache.struts2.views.TagLibrary" name="s" class="org.apache.struts2.views.DefaultTagLibrary" />
<bean class="org.apache.struts2.views.freemarker.FreemarkerManager" name="struts" optional="true"/>
<bean class="org.apache.struts2.views.velocity.VelocityManager" name="struts" optional="true" />
<bean class="org.apache.struts2.components.template.TemplateEngineManager" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="ftl" class="org.apache.struts2.components.template.FreemarkerTemplateEngine" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="vm" class="org.apache.struts2.components.template.VelocityTemplateEngine" />
<bean type="org.apache.struts2.components.template.TemplateEngine" name="jsp" class="org.apache.struts2.components.template.JspTemplateEngine" />
<bean type="com.opensymphony.xwork2.util.XWorkConverter" name="xwork1" class="com.opensymphony.xwork2.util.XWorkConverter" />
<bean type="com.opensymphony.xwork2.util.XWorkConverter" name="struts" class="com.opensymphony.xwork2.util.AnnotationXWorkConverter" />
<bean type="com.opensymphony.xwork2.TextProvider" name="xwork1" class="com.opensymphony.xwork2.TextProviderSupport" />
<bean type="com.opensymphony.xwork2.TextProvider" name="struts" class="com.opensymphony.xwork2.TextProviderSupport" />
<bean type="org.apache.struts2.components.UrlRenderer" name="struts" class="org.apache.struts2.components.ServletUrlRenderer"/>
<!-- Only have static injections -->
<bean class="com.opensymphony.xwork2.ObjectFactory" static="true" />
<bean class="com.opensymphony.xwork2.util.XWorkConverter" static="true" />
<bean class="com.opensymphony.xwork2.util.OgnlValueStack" static="true" />
<bean class="org.apache.struts2.dispatcher.Dispatcher" static="true" />
<bean class="org.apache.struts2.components.Include" static="true" />
<bean class="org.apache.struts2.dispatcher.FilterDispatcher" static="true" />
<bean class="org.apache.struts2.views.util.ContextUtil" static="true" />
<bean class="org.apache.struts2.views.util.UrlHelper" static="true" />
<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>
<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
<!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample JSON validation stack -->
<interceptor-stack name="jsonValidationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack">
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample i18n stack -->
<interceptor-stack name="i18nStack">
<interceptor-ref name="i18n"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- An example of the params-prepare-params trick. This stack
is exactly the same as the defaultStack, except that it
includes one extra interceptor before the prepare interceptor:
the params interceptor.
This is useful for when you wish to apply parameters directly
to an object that you wish to load externally (such as a DAO
or database or service layer), but can't load that object
until at least the ID parameter has been loaded. By loading
the parameters twice, you can retrieve the object in the
prepare() method, allowing the second params interceptor to
apply the values on the object. -->
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
<!-- A complete stack with all the common interceptors in place.
Generally, this stack should be the one you use, though it
may do more than you need. Also, the ordering can be
switched around (ex: if you wish to have your servlet-related
objects applied before prepare() is called, you'd need to move
servlet-config interceptor up.
This stack also excludes from the normal validation and workflow
the method names input, back, and cancel. These typically are
associated with requests that should not be validated.
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
<!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
</package>
</struts>
看看上面的struts-default.xml中的默認配置,都已經事先定義了若干個攔截器使用。
攔截器的類已經定義在特殊的配置文件中,這個配置文件的名字就叫做struts-default.xml,如果你繼承了struts-default默認的包名,那你就可以使用這些攔截器了,否則你必須在你自己的包中定義攔截器在<interceptors>中進行定義。
Interceptor | Name | Description |
---|---|---|
Alias Interceptor | alias | 在不同的請求之間將參數在不同的名字間轉換,請求內容不變. |
Chaining Interceptor | chain | 讓前面一個Action的屬性可以被后一個Action訪問 |
Checkbox Interceptor | checkbox | Adds automatic checkbox handling code that detect an unchecked checkbox and add it as a parameter with a default (usually 'false') value. Uses a specially named hidden field to detect unsubmitted checkboxes. The default unchecked value is overridable for non-boolean value'd checkboxes. |
Cookie Interceptor | cookie | 使用配置的name、value來設置cookies |
Conversion Error Interceptor | conversionError | 將錯誤從ActionContext中添加到Action的屬性字段中 |
Create Session Interceptor | createSession | 自動地創建HttpSession,用來為需要使用到HttpSession的攔截器服務 |
DebuggingInterceptor | debugging | 提供不同的調試用的頁面來展示內部的數據狀況 |
Execute and Wait Interceptor | execAndWait | 在后臺執行Action,同時將用戶帶到一個中間的等待頁面 |
Exception Interceptor | exception | 將異常定位到一個頁面 |
File Upload Interceptor | fileUpload | 提供文件上傳功能 |
I18n Interceptor | i18n | 記錄用戶選擇的locale |
Logger Interceptor | logger | 輸出Action的名字 |
Message Store Interceptor | store | 存儲或者訪問實現ValidationAware接口的Action類出現的消息、錯誤、字段錯誤等。 |
Model Driven Interceptor | model-driven | 如果一個類實現了ModelDriven,將getModel得到的結果放在ValueStack中 |
Scoped Model Driven Interceptor | scoped-model-driven | 如果一個Action實現了ScopedModelDriven,則這個攔截器會從相應的Scope中取出model,調用Action的setModel方法將其放入Action內部 |
Parameters Interceptor | params | 將請求中的參數設置到Action中去 |
Prepare Interceptor | prepare | 如果Action實現了Preparable,則該攔截器調用Action類的prepare方法 |
Scope Interceptor | scope | 將Action狀態存入Session和Application的簡單方法 |
Servlet Config Interceptor | servletConfig | 提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問 |
Static Parameters Interceptor | staticParams | 從struts.xml文件中將<action>中的<param>下的內容設置到對應的Action中 |
Roles Interceptor | roles | 確定用戶是否具有JAAS指定的Role,否則不予執行 |
Timer Interceptor | timer | 輸出Action執行的時間 |
Token Interceptor | token | 通過Token來避免雙擊 |
Token Session Interceptor | tokenSession | 和Token Interceptory一樣,不過雙擊的時候把請求的數據存儲在Session中 |
Validation Interceptor | validation | 使用action-validation.xml文件中定義的內容校驗提交的數據 |
Workflow Interceptor | workflow | 調用Action的validate的方法,一旦有錯返回,重新定位到INPUT頁面 |
Parameter Filter Interceptor | N/A | 從參數列表中刪除不必要的參數 |
Profiling Interceptor | profiling | 通過參數激活profile |
在struts.xml配置文件中,如果要定義攔截器,需要為攔截器類指定一個攔截器名。定義以<interceptor../>元素來實現。還可以定義<param../>參數子元素,用來對攔截器的參數初始化。當然除了可以定義攔截器還可以定義攔截器棧,我也把它稱之為攔截器鏈。攔截器棧由多個攔截器 組成的一個攔截器鏈。定義攔截器鏈使用<interceptor-stack../>元素,當然在這個元素中還需要定義大量的<interceptor-ref ../>,即該攔截器鏈所包含的攔截器引用。在攔截器鏈定義的<interceptor-ref.../>元素中,其name除了可以是一個攔截器的名稱,也可以是一個其它的攔截器鏈。攔截器鏈與攔截器在本質上并無區別,目的都是為了進行攔截。大家可以去看看struts-default.xml配置文件,其中定義了很多攔截器以及攔截器鏈。其中有一個定義為<default-interceptor-ref name="defaultStack"/>意思是定義了一個默認的攔截器鏈,只要是繼承了struts-default包的包均有該默認的攔截器,當然你也可以定義自己的默認的攔截器鏈。<package name="***" extends ="struts-default">該元素的意思是定義了一個繼承于struts-default包的包,那么該包中的所有action均可使用struts-default.xml中定義的攔截器以及攔截器鏈。其中注意一點,struts-default.xml中定義了一系列的攔截器和攔截器鏈,同時也定義了一個默認的攔截器defaultStack,一電定義了默認的攔截器,那么該攔截器將會對包中的所有的Action起作用,當然如果你的Action中顯式地定義了攔截器,那么默認攔截器將會失去作用,當然如果想不讓他失去作用,那么也必須顯式地定義系統默認的攔截器。
<default-interceptor-ref ..../>元素為<package../>元素的一個子元素配置,如果在某個包中定義了一個默認的攔截器,那么此攔截器將對該包中的所有的Action都是有效的,當然一定要記住,顯式地定義攔截器的情況除外。
當然除了可以使用系統提供的默認的攔截器,我們也可以自定義自己的攔截器。Struts2框架提供了一個定義攔截器的接口Interceptor接口。同時Struts2框架也提供了一個可以用于過濾攔截Action方法的類MethodFilterInterceptor。該類有兩個屬性excludeMethods和includeMethods。分別代表指定攔截器拒絕攔截的方法和需要攔截的方法。例:
public class FilterInterceptor extends MethodFilterInterceptor{
private String name;
protected String doIntercept(ActionInvocation arg0)throws Exception{
//HelloWorld hw=(HelloWorld)arg0.getAction();
String res=arg0.invoke();
return res;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
再看看struts.xml配置文件<package name="struts2tutoial" extends="struts-default">
<interceptors>
<interceptor name="MyInterceptor" class="interceptor.MyInterceptor"/>
<interceptor name="FilterInterceptor" class="interceptor.FilterInterceptor"/>
</interceptors>
<action name="HelloWorld" class="helloWorld">
<result>/helloWorld.jsp</result>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="MyInterceptor"/>
<interceptor-ref name="FilterInterceptor">
<param name="includeMethods">***</param>
<param name="excludeMethods">***</param>
</interceptor-ref>
</action>
</package>
可以看到<param../>元素在此處發揮了作用,自定義的FilterInterceptor起到了過濾方法的作用。
歡迎網友參與討論交流!