本文為本人翻譯struts2的官方網(wǎng)站上的關(guān)于攔截器的說明文檔,官方網(wǎng)站上的說明均是英文的,不方便熱愛學(xué)習(xí)而英語又不太好的朋友。該說明文檔地址是http://struts.apache.org/2.0.11/docs/interceptors.html。
許多的Struts2中的Action需要共享一些共用信息或者是模塊,有些Action需要對(duì)輸入進(jìn)行驗(yàn)證,另外一些Action或許需要對(duì)文件上傳之前做一些邏輯處理,又或者一些Action需要對(duì)重復(fù)提交進(jìn)行保護(hù),還有一些Actiion需要在頁面顯示前,初始化下拉框或一些頁面組件。
Struts2框架使用了Interceptor(攔截器)策略使共享這些關(guān)心的模塊更簡(jiǎn)單的使用起來。當(dāng)需要使用到一些映射到Action的資源時(shí),框架生成了Action對(duì)象,但在該Action被執(zhí)行前,執(zhí)法該Action中的方法被另外一個(gè)對(duì)象攔截了,在Action執(zhí)行時(shí),可能再次被攔截,我們親切地稱此對(duì)象為攔截器。
理解攔截器
攔截器能夠在一個(gè)Action執(zhí)行前后攔截它。目前的很多框架的核心實(shí)現(xiàn)均是基于攔截器。(本人說兩句,OOP因?yàn)閿r截器而顯得更為精彩,AOP必將成為下一個(gè)核心關(guān)注點(diǎn))。攔截器可以幫助實(shí)現(xiàn)很多公共的內(nèi)容,其中有重復(fù)提交,類型轉(zhuǎn)換,對(duì)象初始化,驗(yàn)證,文件上傳,頁面初始化等等。由于每個(gè)攔截器都可以像熱插拔的模塊,你可以在你的Action中正確地去使用需要的攔截器。
攔截器可以配置在一個(gè)基類的action中,自定義的攔截器可以盡量少或者配合框架中的已有的攔截器。
所以套用句外國(guó)人的話說吧,在一個(gè)Action執(zhí)行時(shí),讓我們?yōu)樗偬嵘恍┌?,給Action更大
的舞臺(tái)更強(qiáng)大的力量吧。
如上圖所示,Struts2的Action被一個(gè)或者多個(gè)攔截器圍繞,所有的用戶請(qǐng)求都會(huì)被攔截器 所攔截,最后交給Action處理,處理結(jié)果以邏輯視圖的方式返回給用戶,調(diào)用的流程由配置文件來實(shí)現(xiàn)。
在一些例子中,一個(gè)攔截器可以解決像重復(fù)提交以及驗(yàn)證失敗這樣的例子。當(dāng)然也可以改變一個(gè)Action在執(zhí)行前的狀態(tài)。
攔截器可以定義為一個(gè)指定執(zhí)行順序的鏈中,在某些情況下,攔截器的順序非常的重要。
看看上面的配置如果不明白的話,再去看看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中的默認(rèn)配置,都已經(jīng)事先定義了若干個(gè)攔截器使用。
攔截器的類已經(jīng)定義在特殊的配置文件中,這個(gè)配置文件的名字就叫做struts-default.xml,如果你繼承了struts-default默認(rèn)的包名,那你就可以使用這些攔截器了,否則你必須在你自己的包中定義攔截器在<interceptors>中進(jìn)行定義。
個(gè)人理解
在struts.xml配置文件中,如果要定義攔截器,需要為攔截器類指定一個(gè)攔截器名。定義以<interceptor../>元素來實(shí)現(xiàn)。還可以定義<param../>參數(shù)子元素,用來對(duì)攔截器的參數(shù)初始化。當(dāng)然除了可以定義攔截器還可以定義攔截器棧,我也把它稱之為攔截器鏈。攔截器棧由多個(gè)攔截器 組成的一個(gè)攔截器鏈。定義攔截器鏈?zhǔn)褂?lt;interceptor-stack../>元素,當(dāng)然在這個(gè)元素中還需要定義大量的<interceptor-ref ../>,即該攔截器鏈所包含的攔截器引用。在攔截器鏈定義的<interceptor-ref.../>元素中,其name除了可以是一個(gè)攔截器的名稱,也可以是一個(gè)其它的攔截器鏈。攔截器鏈與攔截器在本質(zhì)上并無區(qū)別,目的都是為了進(jìn)行攔截。大家可以去看看struts-default.xml配置文件,其中定義了很多攔截器以及攔截器鏈。其中有一個(gè)定義為<default-interceptor-ref name="defaultStack"/>意思是定義了一個(gè)默認(rèn)的攔截器鏈,只要是繼承了struts-default包的包均有該默認(rèn)的攔截器,當(dāng)然你也可以定義自己的默認(rèn)的攔截器鏈。<package name="***" extends ="struts-default">該元素的意思是定義了一個(gè)繼承于struts-default包的包,那么該包中的所有action均可使用struts-default.xml中定義的攔截器以及攔截器鏈。其中注意一點(diǎn),struts-default.xml中定義了一系列的攔截器和攔截器鏈,同時(shí)也定義了一個(gè)默認(rèn)的攔截器defaultStack,一電定義了默認(rèn)的攔截器,那么該攔截器將會(huì)對(duì)包中的所有的Action起作用,當(dāng)然如果你的Action中顯式地定義了攔截器,那么默認(rèn)攔截器將會(huì)失去作用,當(dāng)然如果想不讓他失去作用,那么也必須顯式地定義系統(tǒng)默認(rèn)的攔截器。
<default-interceptor-ref ..../>元素為<package../>元素的一個(gè)子元素配置,如果在某個(gè)包中定義了一個(gè)默認(rèn)的攔截器,那么此攔截器將對(duì)該包中的所有的Action都是有效的,當(dāng)然一定要記住,顯式地定義攔截器的情況除外。
當(dāng)然除了可以使用系統(tǒng)提供的默認(rèn)的攔截器,我們也可以自定義自己的攔截器。Struts2框架提供了一個(gè)定義攔截器的接口Interceptor接口。同時(shí)Struts2框架也提供了一個(gè)可以用于過濾攔截Action方法的類MethodFilterInterceptor。該類有兩個(gè)屬性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../>元素在此處發(fā)揮了作用,自定義的FilterInterceptor起到了過濾方法的作用。
歡迎網(wǎng)友參與討論交流!
許多的Struts2中的Action需要共享一些共用信息或者是模塊,有些Action需要對(duì)輸入進(jìn)行驗(yàn)證,另外一些Action或許需要對(duì)文件上傳之前做一些邏輯處理,又或者一些Action需要對(duì)重復(fù)提交進(jìn)行保護(hù),還有一些Actiion需要在頁面顯示前,初始化下拉框或一些頁面組件。
Struts2框架使用了Interceptor(攔截器)策略使共享這些關(guān)心的模塊更簡(jiǎn)單的使用起來。當(dāng)需要使用到一些映射到Action的資源時(shí),框架生成了Action對(duì)象,但在該Action被執(zhí)行前,執(zhí)法該Action中的方法被另外一個(gè)對(duì)象攔截了,在Action執(zhí)行時(shí),可能再次被攔截,我們親切地稱此對(duì)象為攔截器。
理解攔截器
攔截器能夠在一個(gè)Action執(zhí)行前后攔截它。目前的很多框架的核心實(shí)現(xiàn)均是基于攔截器。(本人說兩句,OOP因?yàn)閿r截器而顯得更為精彩,AOP必將成為下一個(gè)核心關(guān)注點(diǎn))。攔截器可以幫助實(shí)現(xiàn)很多公共的內(nèi)容,其中有重復(fù)提交,類型轉(zhuǎn)換,對(duì)象初始化,驗(yàn)證,文件上傳,頁面初始化等等。由于每個(gè)攔截器都可以像熱插拔的模塊,你可以在你的Action中正確地去使用需要的攔截器。
攔截器可以配置在一個(gè)基類的action中,自定義的攔截器可以盡量少或者配合框架中的已有的攔截器。
所以套用句外國(guó)人的話說吧,在一個(gè)Action執(zhí)行時(shí),讓我們?yōu)樗偬嵘恍┌?,給Action更大

如上圖所示,Struts2的Action被一個(gè)或者多個(gè)攔截器圍繞,所有的用戶請(qǐng)求都會(huì)被攔截器 所攔截,最后交給Action處理,處理結(jié)果以邏輯視圖的方式返回給用戶,調(diào)用的流程由配置文件來實(shí)現(xiàn)。
在一些例子中,一個(gè)攔截器可以解決像重復(fù)提交以及驗(yàn)證失敗這樣的例子。當(dāng)然也可以改變一個(gè)Action在執(zhí)行前的狀態(tài)。
攔截器可以定義為一個(gè)指定執(zhí)行順序的鏈中,在某些情況下,攔截器的順序非常的重要。
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應(yīng)用中,我們發(fā)現(xiàn)會(huì)一再地重復(fù)應(yīng)用一些攔截器的設(shè)置。重復(fù)地定義一系列的攔截器是個(gè)麻煩的事,當(dāng)然我們可以綁定這些攔截器到一個(gè)鏈中。
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中的默認(rèn)配置,都已經(jīng)事先定義了若干個(gè)攔截器使用。
攔截器的類已經(jīng)定義在特殊的配置文件中,這個(gè)配置文件的名字就叫做struts-default.xml,如果你繼承了struts-default默認(rèn)的包名,那你就可以使用這些攔截器了,否則你必須在你自己的包中定義攔截器在<interceptors>中進(jìn)行定義。
Interceptor | Name | Description |
---|---|---|
Alias Interceptor | alias | 在不同的請(qǐng)求之間將參數(shù)在不同的名字間轉(zhuǎn)換,請(qǐng)求內(nèi)容不變. |
Chaining Interceptor | chain | 讓前面一個(gè)Action的屬性可以被后一個(gè)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來設(shè)置cookies |
Conversion Error Interceptor | conversionError | 將錯(cuò)誤從ActionContext中添加到Action的屬性字段中 |
Create Session Interceptor | createSession | 自動(dòng)地創(chuàng)建HttpSession,用來為需要使用到HttpSession的攔截器服務(wù) |
DebuggingInterceptor | debugging | 提供不同的調(diào)試用的頁面來展示內(nèi)部的數(shù)據(jù)狀況 |
Execute and Wait Interceptor | execAndWait | 在后臺(tái)執(zhí)行Action,同時(shí)將用戶帶到一個(gè)中間的等待頁面 |
Exception Interceptor | exception | 將異常定位到一個(gè)頁面 |
File Upload Interceptor | fileUpload | 提供文件上傳功能 |
I18n Interceptor | i18n | 記錄用戶選擇的locale |
Logger Interceptor | logger | 輸出Action的名字 |
Message Store Interceptor | store | 存儲(chǔ)或者訪問實(shí)現(xiàn)ValidationAware接口的Action類出現(xiàn)的消息、錯(cuò)誤、字段錯(cuò)誤等。 |
Model Driven Interceptor | model-driven | 如果一個(gè)類實(shí)現(xiàn)了ModelDriven,將getModel得到的結(jié)果放在ValueStack中 |
Scoped Model Driven Interceptor | scoped-model-driven | 如果一個(gè)Action實(shí)現(xiàn)了ScopedModelDriven,則這個(gè)攔截器會(huì)從相應(yīng)的Scope中取出model,調(diào)用Action的setModel方法將其放入Action內(nèi)部 |
Parameters Interceptor | params | 將請(qǐng)求中的參數(shù)設(shè)置到Action中去 |
Prepare Interceptor | prepare | 如果Action實(shí)現(xiàn)了Preparable,則該攔截器調(diào)用Action類的prepare方法 |
Scope Interceptor | scope | 將Action狀態(tài)存入Session和Application的簡(jiǎn)單方法 |
Servlet Config Interceptor | servletConfig | 提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問 |
Static Parameters Interceptor | staticParams | 從struts.xml文件中將<action>中的<param>下的內(nèi)容設(shè)置到對(duì)應(yīng)的Action中 |
Roles Interceptor | roles | 確定用戶是否具有JAAS指定的Role,否則不予執(zhí)行 |
Timer Interceptor | timer | 輸出Action執(zhí)行的時(shí)間 |
Token Interceptor | token | 通過Token來避免雙擊 |
Token Session Interceptor | tokenSession | 和Token Interceptory一樣,不過雙擊的時(shí)候把請(qǐng)求的數(shù)據(jù)存儲(chǔ)在Session中 |
Validation Interceptor | validation | 使用action-validation.xml文件中定義的內(nèi)容校驗(yàn)提交的數(shù)據(jù) |
Workflow Interceptor | workflow | 調(diào)用Action的validate的方法,一旦有錯(cuò)返回,重新定位到INPUT頁面 |
Parameter Filter Interceptor | N/A | 從參數(shù)列表中刪除不必要的參數(shù) |
Profiling Interceptor | profiling | 通過參數(shù)激活profile |
在struts.xml配置文件中,如果要定義攔截器,需要為攔截器類指定一個(gè)攔截器名。定義以<interceptor../>元素來實(shí)現(xiàn)。還可以定義<param../>參數(shù)子元素,用來對(duì)攔截器的參數(shù)初始化。當(dāng)然除了可以定義攔截器還可以定義攔截器棧,我也把它稱之為攔截器鏈。攔截器棧由多個(gè)攔截器 組成的一個(gè)攔截器鏈。定義攔截器鏈?zhǔn)褂?lt;interceptor-stack../>元素,當(dāng)然在這個(gè)元素中還需要定義大量的<interceptor-ref ../>,即該攔截器鏈所包含的攔截器引用。在攔截器鏈定義的<interceptor-ref.../>元素中,其name除了可以是一個(gè)攔截器的名稱,也可以是一個(gè)其它的攔截器鏈。攔截器鏈與攔截器在本質(zhì)上并無區(qū)別,目的都是為了進(jìn)行攔截。大家可以去看看struts-default.xml配置文件,其中定義了很多攔截器以及攔截器鏈。其中有一個(gè)定義為<default-interceptor-ref name="defaultStack"/>意思是定義了一個(gè)默認(rèn)的攔截器鏈,只要是繼承了struts-default包的包均有該默認(rèn)的攔截器,當(dāng)然你也可以定義自己的默認(rèn)的攔截器鏈。<package name="***" extends ="struts-default">該元素的意思是定義了一個(gè)繼承于struts-default包的包,那么該包中的所有action均可使用struts-default.xml中定義的攔截器以及攔截器鏈。其中注意一點(diǎn),struts-default.xml中定義了一系列的攔截器和攔截器鏈,同時(shí)也定義了一個(gè)默認(rèn)的攔截器defaultStack,一電定義了默認(rèn)的攔截器,那么該攔截器將會(huì)對(duì)包中的所有的Action起作用,當(dāng)然如果你的Action中顯式地定義了攔截器,那么默認(rèn)攔截器將會(huì)失去作用,當(dāng)然如果想不讓他失去作用,那么也必須顯式地定義系統(tǒng)默認(rèn)的攔截器。
<default-interceptor-ref ..../>元素為<package../>元素的一個(gè)子元素配置,如果在某個(gè)包中定義了一個(gè)默認(rèn)的攔截器,那么此攔截器將對(duì)該包中的所有的Action都是有效的,當(dāng)然一定要記住,顯式地定義攔截器的情況除外。
當(dāng)然除了可以使用系統(tǒng)提供的默認(rèn)的攔截器,我們也可以自定義自己的攔截器。Struts2框架提供了一個(gè)定義攔截器的接口Interceptor接口。同時(shí)Struts2框架也提供了一個(gè)可以用于過濾攔截Action方法的類MethodFilterInterceptor。該類有兩個(gè)屬性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../>元素在此處發(fā)揮了作用,自定義的FilterInterceptor起到了過濾方法的作用。
歡迎網(wǎng)友參與討論交流!