struts2学习之---拦截器机制

本文详细介绍了Struts2框架中的拦截器体系,包括拦截器的作用、配置方法、执行顺序等核心内容。并讲解了如何自定义拦截器及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拦截器体系是struts2框架的重要组成部分,可以把struts2理解成一个空容器,而大量的内建拦截器完成了该框架的大部分操作。比如:param拦截器负责解析HTTP请求的参数,并设置Action的属性;servlet-config拦截器直接将HTTP请求中的HttpServletRequest实例和HttpServletResponse实例传给Action;fileUpload拦截器则负责解析请求参数中的文件域,并将一个文件域设置成Action的三个属性。
struts2拦截器是可插拔式的拦截器。

1.拦截器在struts2中的作用

struts2框架的绝大部分功能都是通过拦截器来完成的。当StrutsPrepareAndExecuteFilter拦截到用户请求之后,大量拦截器将会对用户请求进行处理,然后才会调用用户开发的Action实例的方法来处理用户请求。
拦截器与Action的关系:StrutsPrepareAndExecuteFilter初始化一个AcitonProxy实例,并调用它的execute()方法,拦截器方法会先拦截,并处理用户请求,然后才到Action的execute方法处理用户请求,返回一个逻辑视图名,系统负责将逻辑视图对应的资源呈现给用户。
struts2已经默认启用了大量通用功能的拦截器,只要配置Action时所在的package继承了struts-default包,这些拦截器就会起作用。

2.配置拦截器

在struts.xml文件中定义拦截器只需为拦截器类指定一个拦截器名。

    <interceptor name="拦截器名" class="拦截器实现类"/>

如果需要在配置拦截器时传入拦截器参数,则需要在<interceptor.../>元素中使用<param.../>子元素。

<package name="">
  <interceptors>
    <interceptor name="拦截器名" class="拦截器实现类">
        <param name="参数名">参数值</param>
    </interceptor>
  <interceprors>
</package>

把多个拦截器连在一起组成拦截器栈,如果需要在Action执行前同时做登录检查,安全检查和记录日志,则可以把这三个动作对应的拦截器组成一个拦截器栈。

    <interceptor-stack name="拦截器栈名">
        <interceptor-ref name="拦截器一"/>
        <interceptor-ref name="拦截器二"/>
        ...
    </interceptor-stack>

因为拦截器栈与拦截器的功能几乎完全相同,因此可能出现的是拦截器栈里也可包含拦截器栈。
系统为拦截器指定参数有如下两个时机:

  • 定义拦截器时指定参数值:这种参数值将作为拦截器参数的默认参数值。通过<interceptor>元素来定义拦截器。
  • 使用拦截器时指定参数值:在配置Action时拦截器参数指定值。通过<interceptor-ref>元素来使用拦截器。
    使用拦截器时指定的参数值将会覆盖默认的参数值。
3.使用拦截器的配置语法

一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了,拦截器(包含拦截器栈)的拦截行为将会在Action的execute方法执行之前被执行。
通过<interceptor-ref.../>元素可以在Action内使用拦截器。

    <action name="" calss="">
        <interceptor-ref name="拦截器名或拦截器栈名"/>
        <interceptor-ref name="拦截器名或拦截器栈名"/>
    </action>
4.配置默认拦截器

当配置一个包时,可以为其指定默认拦截器。一旦为某个包指定了默认的拦截器,如果该包中的Action没有显示指定拦截器,则默认的拦截器将会起作用。一旦为该包中的Action显示应用了某个拦截器,则默认的拦截器不会起作用,如果该Action还需要使用该默认拦截器,则必须手动配置该拦截器的引用。

    <package name="">
        <default-inerceptor-ref name="已经存在的拦截器或拦截器栈名"/>
    </package>

每个<package...>元素只能有一个<default-interceptor-ref.../>子元素,即每个包只能指定一个默认拦截器。
配置默认拦截器是一种使用拦截器的方式—避免在每个Action中单独配置拦截器,通过在该包下配置拦截器,可以实现为该包下所有Action同时配置相同的拦截器。

struts-default.xml
<struts>
    <package name="struts-default">
        <default-interceptor-ref name="defaultStack"/>
    </package>
</struts>

拦截器相关配置如下:

  • <interceptors.../>元素:该元素用于定义拦截器。该元素包含<interceptor.../><interceptor-stack.../>子元素用于定义拦截器和拦截器栈。
  • <interceptor.../>:该元素用于定义单个拦截器,指定name和class属性,分别指定拦截器的名字和实现类。
  • <interceptor-stack.../>:该元素用于定义拦截器栈。包含多个<interceptor-ref.../>元素,用于将多个拦截器或拦截器栈组合成一个新的拦截器栈。
  • <interceptor-ref.../>:该元素引用一个拦截器或拦截器栈,表明应用指定拦截器。name属性,该属性值为一个已经定义的拦截器或拦截器栈。该元素可以作为<interceptor-stack.../><action.../>元素的子元素使用。
  • <param.../>:该元素用于为拦截器指定参数,可以作为<interceptor.../><interceptor-ref.../>元素的子元素使用。
  • <default-interceptor-ref.../>:该元素为指定包配置默认拦截器。该元素作为<package.../>元素的子元素使用。
5.实现拦截器类

如果用户要开发自己的拦截器类,应该实现com.opensymphony.xwork2.interceptor.Interceptor接口。

    public interface Interceptor extends Serializable{
        void destroy();
        void init();
        String intercept(ActionInvocation invocation) throws Exception;
    }
  • init():在该拦截器被实例化之后,在该拦截器执行拦截之前,系统将回调该方法。该方法的方法体主要用于初始化资源。
  • destroy():在拦截器实例被销毁之前,系统将回调该拦截器的destory方法,该方法用于销毁在init()方法里打开的资源。
  • intercept():该方法是用户需要实现的拦截动作。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过调用该参数的invoke方法,将控制权转给下一个拦截器,或者转给Action的execute方法。

struts2还提供了一个AbstractInterceptor类,该类提供了一个init()和destory()方法的空实现,如果实现的拦截器不需要打开资源,则无须实现这两个方法。

6.拦截方法的拦截器

在某些情况下,如果不想拦截所有的方法,只需要拦截指定方法,此时就需要使用struts2拦截器的发放过滤特性。
为了实现方法过滤特性,struts2提供了一个MethodFilterInterceptor类,该类是AbstractInterceptor类的子类。MethodFilterInterceptor类重写了AbstractInterceptor类的intercept()方法,但提供了一个doIntercept()抽象方法。
实际上方法过滤的拦截器与实现普通拦截器并没有太大的区别,只需要注意的是:实现方法过滤的拦截器需要继承MethodFilterInterceptor抽象类,并且重写doIntercept()方法定义对Action的拦截逻辑。
在MethodFilterInterceptor方法中,额外增加如下两个方法:

  • public void setExcludeMethods(String execludeMethods):排除需要过滤的方法—设置方法“黑名单”,所有在excludeMethods字符串中列出的方法都不会被拦截。
  • public void setIncludeMethods(String includeMethods):设置需要过滤的方法—设置方法“白名单”,所有在includeMethods字符串中列出的方法都会被拦截。
    如果一个方法同时在excludeMethods和includeMethods中列出,则该方法会被拦截。
<action name="" class="">
    <interceptor-ref name="">
        <param name="excludeMethods">execute</param>
    </interceptor>
</action>

struts2中提供了这种方法过滤的拦截器有如下几个:

  • TokenInterceptor
  • TokenSessionStoreInterceptor
  • DefaultWorkflowInterceptor
  • ValidationInterceptor
7.拦截器的执行顺序

在Action的控制方法执行之前,位于拦截器链前面的拦截器将先发生作用;在Action的控制方法执行之后,位于拦截器链前面的拦截器将后发生作用。

8.拦截结果的监听器

为了精确定义在execute()方法执行结束后,在处理物理资源转向之前的动作,struts2提供了用于拦截结果的监听器,这个监听器是用过手动注册在拦截器内部的。
PreResultListener,把该监听器注册在拦截器中,这样可以只要该拦截器起作用的地方,这个拦截接口的监听器都会被触发。

    public class MyPreResultListener implements PreResultListener{
        public void beforeResult(ActionInvocation invocation,String resultCode){

        }
    }

public class BeforeResultInterceptor extends AbstractInterceptor{
        public String intercept(ActionInvocation invocation){
            invocation.addPreResultListener(new MyPreResultListener());
        }
    }

resultCode,这个参数就是被拦截的Action的被拦截方法的返回值。
不要在PreResultListener监听器的beforeResult方法中通过ActionInvocation参数调用invoke()方法。

9.覆盖拦截器栈里特定拦截器的参数

有时候,Action需要使用一个拦截器栈,当使用这个拦截器栈时,又需要覆盖该拦截器栈中某个拦截器的指定参数值。此时需要在配置使用拦截器栈的<interceptor-ref.../>元素中使用<param.../>元素来传入参数,在<param.../>元素中指定参数名时应使用<拦截器名>.<参数名>这种方式。

<package name="">
    <interceptors>
        <interceptor-ref name="first">
            <param name="name">第一个</param>
        </interceptor-ref>
    <interceptors>
    <action name="" class="">
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="first">
            <param name="first.name">改名后的拦截器</param>
        </interceptor-ref>
    </action>
</package>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值