Struts2学习:拦截器篇(一)

来源:互联网 发布:淘宝销量前十名店铺 编辑:程序博客网 时间:2024/05/02 02:55

Struts2中自带的默认拦截器栈已经能够满足大多数应用的需要了,大多数的应用都不必再增加自己的拦截器或者改变已有的拦截器栈。在Struts2中,许多action通常都有一些共同的需要关心的问题,比如有一些action它们都需要对页面上的输入进行验证,有一些action需要对上传的文件进行一下预处理,还有一些action可能需要防止重复提交(double submit),还有很多action需要在页面显示之前将下拉列表和者其它的一些控件事先装好值。通过使用“拦截器”策略,Struts2框架使得共享这些问题的解决方案变得十分容易。当我们请求一个action的时候,框架会调用这个action对象,但是,在action执行之前,这个调用可能会被另外一个对象所拦截,就像导弹也会被拦截一样,^_^。在action执行之后,这个调用可能被一个对象再次拦截,顾名思义,我们称这些用于拦截的对象为拦截器。

拦截器能在action被调用之前和被调用之后执行一些“代码”。Struts2框架的大部分核心功能都是通过拦截器来实现的,如防止重复提交、类型转换、对象封装、校验、文件上传、页面预装载等等,都是在拦截器的帮助下实现的。每一个拦截器都是独立装载的(pluggable),我们可以根据实际的需要为每一个action配置它所需要的拦截器,例如,一个action需要用来类型装换、文件上传,那么我们可以给它设置相应的两个拦截器。

我们可以为每个action单独设置拦截器,我们自己定制的拦截器可以和Struts2框架自带的拦截器一起配合使用。拦截器为action布置好了它运行的“舞台”,并且在action执行之前把很多准备工作都做好了。Action的生命周期如下图所示:

在有些情况下,拦截器可能阻止一个action执行,例如重复提交的情况下或者校验没有通过的情况下,除此之外,拦截器还能在一个action执行之前改变它的状态。拦截器被定义在栈中,这个栈指定了拦截器的执行顺序,在有些情况下,拦截器在栈中的顺序是非常重要的。下面是一个简单的拦截器配置的例子:

<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应用中,我们会发现有一些拦截器会一次又一次的被使用,为了避免重复的列出这些拦截器,我们可以将这些常用的拦截器捆绑在一起,形成已给拦截器栈,如下所示:

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

Struts2自带的struts-default.xml文件中有很多这样的拦截器和拦截器栈的例子,所有的拦截器类都是以键值对的形式在Struts配置文件中指定的,可以看下struts-default.xml文件。如果想使用它里面定义好了的拦截器,我们必须继承它里面的struts-default包,否则的话我们要在自己的包里面的<interceptors>标签中定义一个键值对。如<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>,就是一个键值对。

一.方法过滤

    就个人理解,我认为Struts2中的拦截器机制和Spring中的aop是类似的,或者说是同一个原理。在Spring中我们通过切入点来定义对哪些类的哪些方法来进行拦截,在Struts2中我们可以通过两个参数来对需要拦截的方法进行过滤,这两个参数是:excludeMethodsincludeMethods,前者指明不被拦截的方法的集合,后者则指明需要被拦截的方法的集合。如果一个方法既在excludeMethods中又在includeMethods中,那么它仍然被认为是需要进行拦截的,也就是说includeMethods要优先于excludeMethods。当然,并不是所有的拦截器都具有这个功能,只有如下四个拦截器类才具有这样的功能:

    TokenInterceptor

      TokenSessionStoreInterceptor

      DefaultWorkflowInterceptor

        ValidationInterceptor

二.拦截器参数覆盖

       拦截器的参数可以通过如下两种方式被覆盖:一种是直接对拦截器的参数进行覆盖,另外一种是在拦截器栈中对栈中某个拦截器的参数进行覆盖,形式分别如下所示。

方法一:

<action name="myAction" class="myActionClass">

    <interceptor-ref name="exception"/>

    <interceptor-ref name="alias"/>

    <interceptor-ref name="params"/>

    <interceptor-ref name="servlet-config"/>

    <interceptor-ref name="prepare"/>

    <interceptor-ref name="i18n"/>

    <interceptor-ref name="chain"/>

    <interceptor-ref name="model-driven"/>

    <interceptor-ref name="fileUpload"/>

    <interceptor-ref name="static-params"/>

    <interceptor-ref name="params"/>

    <interceptor-ref name="conversionError"/>

    <interceptor-ref name="validation">

      <param name="excludeMethods">myValidationExcudeMethod</param>

    </interceptor-ref>

    <interceptor-ref name="workflow">

      <param name="excludeMethods">myWorkflowExcludeMethod</param>

    </interceptor-ref>

</action>

方法二:

<action name="myAction" class="myActionClass">

  <interceptor-ref name="defaultStack">

    <param name="validation.excludeMethods">myValidationExcludeMethod</param>

    <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param>

  </interceptor-ref>

</action>

    方法一没有使用拦截器栈,它对所使用的拦截器一个个的进行设置,方法二使用了拦截器栈,因此它的覆盖方法有点不同。如果是对栈中的拦截器的参数进行覆盖,参数的paramname属性需要包含一个点号(.),点号之前的部分指代该拦截器栈中需要覆盖参数的拦截器,点号之后的部分则指代需要被覆盖的参数的名称。如上面方法二,它表明defaultStack栈中的validationworkflow拦截器的excludeMethods方法要被覆盖。

 

 
原创粉丝点击