Struts拦截器

Struts拦截器

默认的Interceptor堆栈旨在满足大多数应用程序的需求。大多数应用程序并不需要添加拦截器或改变拦截器栈。

许多行动都有共同的担忧。某些操作需要输入验证。其他操作可能需要预处理文件上载。另一个行动可能需要保护双重提交。许多操作需要在页面显示之前预先填充的下拉列表和其他控件。

该框架使用“拦截器”策略可以轻松地分享这些问题的解决方案。当您请求映射到“操作”的资源时,框架将调用Action对象。但是,在执行Action之前,调用可能会被另一个对象拦截。Action执行后,可以再次拦截调用。不出所料,我们将这些对象称为“拦截器”。

Introducing Interceptors

Struts 2框架在执行Action之前和之后完成的任务由Struts 2拦截器完成。拦截器是Struts 2核心jar中包含的标准Java类,它们按特定顺序执行。

在示例应用程序中,struts.xml中有一个包节点。包节点的属性为extends,其值为“struts-default”。值“struts-default”向框架标识将在该包中的Actions之前和之后执行的特定拦截器堆栈。

有时,Struts 2默认的拦截器堆栈并不是特定操作所需的。您可能希望使用不属于Struts 2默认堆栈的拦截器。对于单个Action或整个Actions包,您可以指定Action或包应使用不同拦截器堆栈。下面是如何指定寄存器Action 除了默认堆栈提供的拦截器外还应使用记录器和定时器拦截器。

拦截器可以在调用Action之前和之后执行代码。框架的大多数核心功能都是作为拦截器实现的。双重提交警卫,类型转换,对象填充,验证,文件上传,页面准备等功能都是在拦截器的帮助下实现的。每个Interceptor都是可插拔的,因此您可以确定Action需要支持哪些功能。

拦截器可以基于每个动作进行配置。您自己的自定义拦截器可以与框架捆绑的拦截器混合和匹配。拦截器为Action类“设置阶段”,在Action执行之前做了很多“繁重的工作”。

行动生活
在这里插入图片描述
在某些情况下,由于双重提交或验证失败,Interceptor可能会阻止Action触发。拦截器还可以在执行之前更改Action的状态。
拦截器在堆栈中定义,指定执行顺序。在某些情况下,堆栈上的拦截器的顺序非常重要。

为动作指定特定拦截器

<action name="register" class="org.apache.struts.register.action.Register" method="execute">
    <interceptor-ref name="timer" />
    <interceptor-ref name="logger" />
    <interceptor-ref name="defaultStack">
        <param name="exception.logEnabled">true</param>
        <param name="exception.logLevel">ERROR</param>
    </interceptor-ref>
    <result name="success">thankyou.jsp</result>
    <result name="input">register.jsp</result>
</action>

记录器拦截器记录Action执行的开始和结束。计时器拦截器记录执行Action的时间量(以毫秒为单位)。这两个拦截器一起使用可以为开发人员提供有用的反馈。

在上面的代码示例中,请注意三个拦截器-ref节点。每个都有name属性的值。对于寄存器操作,我们指示使用的框架timer,logger和defaultStack拦截器。在defaultStack 通常一个动作执行的所有拦截器。

我怎么知道使用timer的值作为name属性,甚至还有一个定时器拦截器?在Struts 2文档中的拦截器网页上有Struts 2框架附带的拦截器列表以及每个拦截器的名称值。

我怎么知道定时器拦截器不是拦截器的defaultStack的一部分?再次在拦截器文档网页上列出了哪些拦截器属于defaultStack。

注意param节点。这些节点用于为Exception Interceptor的setLogEnabled和setLogLevel方法提供值。提供true和ERROR的值将导致Struts 2框架记录未被应用程序代码捕获的任何异常,并在ERROR级别记录这些异常。

为包指定特定拦截器

<package name="basicstruts2" extends="struts-default" > 
    <interceptors> 
        <interceptor-stack name="appDefault"> 
            <interceptor-ref name="timer" /> 
            <interceptor-ref name="logger" /> 
            <interceptor-ref name="defaultStack" /> 
        </interceptor-stack> 
    </interceptors>          

    <default-interceptor-ref name="appDefault" /> 

    <!-- rest of package omitted --> 

</package> 

在上面的代码,我们使用拦截器节点来定义拦截器的新的堆栈,其包括timer,logger,和defaultStack拦截器。我们为这个新的拦截器堆栈命名为appDefault。然后我们使用该default-interceptor-ref 节点指定对于此包节点内定义的所有Actions appDefault,将使用拦截器堆栈。因此timer,logger将为此包中的每个Action执行和拦截器。

请注意,在这两个示例中,我们仍然通过将defaultStack包含为其中一个interceptor-ref节点来执行所有其他拦截器。指定要用于Action或包的拦截器时,只执行那些拦截器。所以,如果在这个例子中,我们已经离开了interceptor-ref的defaultStack只有logger和timer拦截器就会执行。

创建自己的拦截器

除了指定自己的拦截器堆栈之外,您还可以编写自己的新拦截器并将其添加到执行的堆栈中。Struts Writing Interceptors指南解释了如何执行此操作。例如,您可以创建自己的拦截器来处理身份验证和授权。

配置拦截器

在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="redirectAction">/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="redirectAction">/secure/home</result>
   </action>
</package>

从内部看struts-default.xml,我们可以看到它是如何完成的。

框架拦截器

拦截器类也使用Struts配置文件中指定的键值对定义。下面指定的名称在struts-default.xml中指定。如果扩展struts-default 包,则可以使用以下名称。否则,必须在包中使用标记中指定的名称类对定义它们。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法过滤

MethodFilterInterceptor是一个抽象,Interceptor用作拦截器的基类,它将根据指定的包含/排除方法列表根据方法名称过滤执行。

可设置的参数如下: - excludeMethods - 要从拦截器处理中排除的方法名称 - includeMethods - 要包含在拦截器处理中的方法名称

如果includeMethods和excludeMethods中都有方法名称,则它将被视为包含的方法:includeMethods优先于excludeMethods。

扩展此功能的拦截器包括: - TokenInterceptor - TokenSessionStoreInterceptor - DefaultWorkflowInterceptor -ValidationInterceptor

拦截器参数覆盖

拦截器的参数可以通过以下方式覆盖:
方法1:

<action name="myAction" class="myActionClass">
    <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="staticParams"/>
    <interceptor-ref name="params"/>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">myValidationExcludeMethod</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">myWorkflowExcludeMethod</param>
    </interceptor-ref>
</action>

方法2:

<action name="myAction" class="myActionClass">
    <interceptor-ref name="defaultStack">
        <param name="validation.excludeMethods">myValidationExcludeMethod</param>
        <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param>
    </interceptor-ref>
</action>

在第一种方法中,复制整个默认堆栈,然后相应地更改参数。
在第二种方法中,interceptor-ref引用现有的拦截器堆栈,即defaultStack在此示例中,并覆盖validator和workflow拦截器excludeMethods属性。请注意,在param 标记中,name属性包含一个点(。),点之前的单词(。)指定要覆盖其参数的拦截器名称,而点(。)之后的单词指定参数本身。语法如下:

 <interceptor-name>.<parameter-name>

还要注意,在这种情况下,interceptor-refname属性用于指示一个拦截器堆栈,它有意义,好像它指的是拦截器本身,它只是使用上面描述的方法1。

方法3:

<interceptors>
    <interceptor-stack name="parentStack">
        <interceptor-ref name="defaultStack">
            <param name="params.excludeParams">token</param>
        </interceptor-ref>
    </interceptor-stack>
</interceptors>

<default-interceptor-ref name="parentStack"/>

拦截器参数覆盖继承

参数覆盖不会在拦截器中继承,这意味着将使用最后一组重写参数。例如,如果堆栈覆盖“postPrepareParameterFilter”拦截器的参数“defaultBlock”,则:

<interceptor-stack name="parentStack">
  <interceptor-ref name="postPrepareParameterFilter">
    <param name="defaultBlock">true</param>
  </interceptor-ref>
</interceptor-stack>

并且操作会覆盖“postPrepareParameterFilter”的“allowed”:

<package name="child2" namespace="/child" extends="parentPackage">
  <action name="list" class="SomeAction">
    <interceptor-ref name="parentStack">
      <param name="postPrepareParameterFilter.allowed">myObject.name</param>
    </interceptor-ref>
  </action>
</package>

然后,只有“allowed”将被覆盖该动作中的“postPrepareParameterFilter”拦截器,其他参数将为null。

懒惰的参数

可以使用在动作调用期间评估的参数来定义拦截器。在这种情况下,拦截器必须用WithLazyParams接口标记 。这必须是开发人员的决定,因为拦截器必须知道在调用期间设置这些参数,而不是在正常情况下创建拦截器时。

参数被评估为从作为顶级对象的动作开始的任何其他表达式。

<action name="LazyFoo" class="com.opensymphony.xwork2.SimpleAction">
  <result name="success">result.jsp</result>
  <interceptor-ref name="lazy">
    <param name="foo">${bar}</param>
  </interceptor-ref>
</action>
public class MockLazyInterceptor extends AbstractInterceptor implements WithLazyParams {

    private String foo = "";

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public String intercept(ActionInvocation invocation) throws Exception {
        ....
        return invocation.invoke();
    }
}

请注意,当想要访问通过请求传递的参数时,拦截器的顺序可能很重要,因为这些参数是由参数拦截器设置的 。

拦截器执行顺序

拦截器提供了一种在处理之前/之后进行包装的极好方法。这个概念减少了代码重复(想想AOP)。

<interceptor-stack name="xaStack">
  <interceptor-ref name="thisWillRunFirstInterceptor"/>
  <interceptor-ref name="thisWillRunNextInterceptor"/>
  <interceptor-ref name="followedByThisInterceptor"/>
  <interceptor-ref name="thisWillRunLastInterceptor"/>
</interceptor-stack>

实现的拦截器com.opensymphony.xwork2.interceptor.PreResultListener将在Action执行之后但在Result执行之前运行。

thisWillRunFirstInterceptor
  thisWillRunNextInterceptor
    followedByThisInterceptor
      thisWillRunLastInterceptor
        MyAction1
        MyAction2 (chain)
        MyPreResultListener
        MyResult (result)
      thisWillRunLastInterceptor
    followedByThisInterceptor
  thisWillRunNextInterceptor
thisWillRunFirstInterceptor
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值