Struts 2 struts.xml详解(三)

拦截器(Interceptor)配置

        上节简单地介绍了Action的配置,这节简单介绍一下拦截器的配置。

1 拦截器栈的配置

        顾名思义,拦截器就是在action的执行前后实行拦截,加入某些操作。拦截器类似于servlet的过滤器。它们是按照定义的顺序依次执行的。每一个拦截器访问的都是相同的ActionInvocation,就像每个过滤器访问的都是同一个Request。拦截器是通过拦截器栈进行组织的,拦截器栈组织了一系列的拦截器的集合。

        查看struts-default.xml文件的struts-default包,可以看到有两个元素<interceptors>和<interceptor-stack>。

   <interceptors>元素:定义拦截器的名字和类

   <interceptor-stack>元素:将特定的拦截器和拦截器栈组织在一起(拦截器栈中可以包含拦截器栈)

        在struts-default.xml文件中已经定义了一些拦截器:

<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 ="external-ref" 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 ="model-driven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />   
<interceptor name ="scoped-model-driven" 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 ="static-params" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>  
<interceptor name ="scope" class="org.apache.struts2.interceptor.ScopeInterceptor" />   
<interceptor name ="servlet-config" 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 ="token-session" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />   
<interceptor name ="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor" />   
<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"/>
 

        每个拦截器的定义包含了一个唯一的名字和拦截器类的全名(具体包名和类名)。

        在struts-default.xm中已经配置了以上的拦截器。如果您想要使用上述拦截器,只需要在应用程序struts.xml文件中通过“<include file="struts-default.xml" />”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义Action时,使用“<interceptor-ref name="xx" />”引用拦截器或拦截器栈(interceptor stack)。一旦您继承了struts-default包(package),所有Action都会调用拦截器栈——defaultStack。当然,在Action配置中加入“<interceptor-refname="xx" />”可以覆盖defaultStack。

        注:一旦在action中声明了任何一个拦截器,就得声明所有这个action要引用的拦截器,因为默认拦截器已经被覆盖了。

        Struts2提供的拦截器功能说明:

拦截器

名字

说明

Alias Interceptor

alias

在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor

chain

让前一个Action的属性可以被后一个Action访问,现在和chain类型的result(<result type=”chain”>)结合使用。

Checkbox Interceptor

checkbox

添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。

Cookies Interceptor

cookies

使用配置的name,value来是指cookies

Conversion Error Interceptor

conversionError

将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor

createSession

自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor

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得到的结果放在Value Stack中。

Scoped Model Driven

scoped-model-driven

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

Parameters Interceptor

params

将请求中的参数设置到Action中去。

Prepare Interceptor

prepare

如果Acton实现了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 Interceptor一样,不过双击的时候把请求的数据存储在Session中

Validation Interceptor

validation

使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor

workflow

调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor

N/A

从参数列表中删除不必要的参数

Profiling Interceptor

profiling

通过参数激活profile

         拦截器栈组织了一系类拦截器,例如,Struts 2 定义了一个名位basicStack的拦截器栈:

<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>

  

        <interceptor-ref>是用来引用特定的拦截器或拦截器栈。

        在validationWorkflowStack的定义中就引用了拦截器栈basicStack。

<interceptor-stack name="validationWorkflowStack">   
    <interceptor-ref name="basicStack"/>   
    <interceptor-ref name="validation"/>   
    <interceptor-ref name="workflow"/>  
</interceptor-stack>
 

2 拦截器的配置

        拦截器可以通过<param>元素来配置参数。例如,我们可以看到validation的验证可以跳过某一个action的input()方法(对input()方法不执行验证)。配置如下:

<interceptor-stack name="validationWorkflowStack">   
    ...   
    <interceptor-ref name="validation">   
        <param name="excludeMethods">   
            input,back,cancel,browse   
        </param>   
    </interceptor-ref>  
    ...

   

        这是因为validation拦截器是MethodFilterInterceptor的子类,MethodFilterInterceptor定义了一个excludeMethods的参数(还有includeMethods参数)。这个参数是以逗号分隔符解析出一系列不进行拦截的方法名的。以上的配置就是对input,back,cancel,browse等方法不进行拦截验证。

        假设已经定义了一个拦截器栈defaultStack并且该拦截器栈包含了validation拦截器,而且我们有一个action要用到defaultStack拦截器栈,但是它有一个方法doNotValidate()不需要进行validation验证,怎么办呢?

        也许你会这样配置:

<action name="errorConfiguration" class="com.stuqbx.web.action.ErrorAction">  
    <interceptor-ref name="validation">   
        <param name="excludeMethods">  
            input,back,cancel,browse,doNotValidate   
        </param>  
    </interceptor-ref>  
</action>
 

        但是,这样配置运行之后,会发现其他的拦截器不起作用了,如前面所说的,action中一旦声明了拦截器,就得把要用到 拦截器都声明了。为此,可能要把defaultStack中所有的拦截器都在声明一遍,这太麻烦了。其实,我们还可以这样:

<action name="correctConfiguration" class="com.stuqbx.web.action.CorrectAction">   
    <interceptor-ref name="defaultStack">   
        <param name="validation.excludeMethods">  
            input,back,cancel,browse,doNotValidate  
        </param>  
    </interceptor-ref>  
</action>

   

        这配置了一个action,该action用到了defaultStack拦截器栈,并且为其中的validation拦截器的excludeMethods参数配置了相应的值。配置的语法很简单,用interceptorName.parameterName作为param的name。还有如果在action中用到了一个拦截器栈,这个拦截器栈中又引用了多个拦截器栈,也可以为其中的某些拦截器配置相应的参数,语法为:stackName.interceptorName.parameterName。

3 默认拦截器

        在package中可以用<default-interceptor-ref>来定义默认的拦截器。例如,在struts-default包中就定义了默认的拦截器:

<package name="struts-default" abstract="true">   
    <!-- ... -->   
    <default-interceptor-ref name="defaultStack"/>  
</package>

  

4 拦截器工作原理

        所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。该接口提供了三个方法:

void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。

void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前,系统将回调该方法。

String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。

        除此之外,继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor是更简单的一种实现拦截器类的方式,因为此类提供了init()和destroy()方法的空实现,这样我们只需要实现intercept方法。

        有些拦截器处理是跟action的调用无关的,有些拦截器只有在action实现了某些特定的接口时才执行。ActionInvocation有一个action的属性,存储了被调用的action的了实例。通过用instanceof检查是被调用的action是哪一个,拦截器就可以决定是否拦截处理。

         在自定义拦截器时,拦截器必须是无状态的,不要使用在API提供的ActionInvocation之外的任何东西。拦截器是无状态的是因为Struts 2不能保证为每一个请求或者action创建一个拦截器的实例,所以如果拦截器带有状态,会引发并发问题。

相关推荐