Struts2--拦截器详解

一、拦截器是啥

    刚接触struts的筒子们一般会直接去研究action,那咱们就从action说起。先举一个html中form标签的例子:

<form action="myaction.action">
    <input name="name" type="text">
    <input name="password" type="password">
    <input type="submit">
</form>

    我们知道,点击提交之后,名为"input"和"password"的两个input的值会自动传给myaction中的"input"和"password"的两个属性。这种自动赋值让筒子们感觉很舒服,而其中赋值的工作就是由拦截器做的。拦截器,顾名思义,其作用就是"拦截"。它到底拦截了啥?答案是"客户端请求"。也就是说,拦截器的存在就是为了在action之前根据客户端请求做一些工作。

二、拦截器的配置

    拦截器是“无状态”的组件,它像一个普通的零件一样,可以随意安装到一个action上,或者从一个action上拆下来。或安装,或拆卸,都是在配置文件中配置的(一般是struts.xml)。

    1.单一拦截器的“安装”

     如果是系统自带的拦截器,那直接在<action></action>标签之间添加即可。

<action name="a" class="com.hao.service.A">
    <result name="success">/a.jsp</result>
    <!-- 下面这个标签在action中配置了文件上传拦截器 -->
    <interceptor-ref name="fileUpload"/>
</action>

    如果是自己写的拦截器,那就还要多一步配置,就是声明你的拦截器是存在的。咋声明呢?还是在struts.xml中:

<interceptors>

    <!-- name属性指定拦截器名称,class属性指定该拦截器的实现类 -->
    <interceptor name="inter1" class="com.hao.interceptors.Inter1"/>

    <interceptor name="inter2" class="com.hao.interceptors.Inter2"/>

</interceptors>
    这样,在struts.xml中给你的拦截器做了一个清单之后,你就可以直接在action中添加了。
    2.拦截器栈的“安装”

    拦截器栈就是拦截器的集合,它存在的意义就是可以让我们一次性完成多个拦截器的“安装”。在“安装”自定义的拦截器栈之前,也是要在struts.xml中声明该栈的存在,同样也是放在<interceptors></interceptors>标签之间(拦截器和拦截器栈其实是处在等同的地位)。

<interceptors>
    
    <interceptor-stack name="myStack">
    
        <!-- 注意,下面拦截器列出的顺序决定了执行的顺序 -->
        <interceptor-ref name="inter1" />

        <interceptor-ref name="inter2" />

    </interceptor-stack>

</interceptors>

    之后就可以一次性在action中配置这两个拦截器

<action name="a" class="com.hao.service.A">
    
    <!-- 其实和配置单一拦截器是一样的 -->
    <interceptor-ref name="myStack"/>

</action>
    3.关于“默认拦截器栈”
    只要在struts.xml中把<package>标签的extends属性的值指定为“struts-default”(其实基本都会这么做),那你的action就被默认配置了"default-stack"这个拦截器栈(尽管你没有添加interceptor标签),这个拦截器栈中的拦截器做了struts中绝大多数的常规工作,如“表单的值自定赋给action属性”(这个是由default-stack中的params拦截器实现的)。至于defaultStack里都有哪些拦截器,参见《 struts2中自带的拦截器和defaultStack拦截器栈》。不过呢,有个问题,就是当你在action标签中用interceptor标签显示配置了拦截器之后,那默认的拦截器栈将不会自动被配置到该action中,你需要像配置其它拦截器栈一样显式的配置默认拦截器栈(这个机制挺像很多编程语言中“默认构造函数”的)。如果你想把默认拦截器栈由"default-stack"改为自定义的,你可以用default-stack-ref标签:

<interceptors>
    
    <interceptor-stack name="myStack">
    
        <interceptor-ref name="inter1" />

        <interceptor-ref name="inter2" />

    </interceptor-stack>

</interceptors>

<!-- 在这 -->
<default-stack-ref name="myStack"/>

<action name="a" class="com.hao.service.A">
    
    <result name="success">/a.jsp</result>

</action>

<action name="b" class="com.hao.service.B">
    
    <result name="success">/b.jsp</result>

</action>

三、拦截器的java实现

    自定义的拦截器要实现Interceptor接口,该接口代码如下

public interface Interceptor extends Serializable {

    void destroy();

    void init();

    String intercept(ActionInvocation invocation) throws Exception;

}
    该接口有三个方法,init()做一些申请资源之类的初始化工作,destroy()则在该拦截器生命周期结束后做相反的工作,intercept (ActionInvocation invocation)是主要的业务方法,拦截工作就写在该方法中。接下来就说说这个主要业务方法的返回值和参数。该方法返回值是String类型,其作用和action中的execute方法的返回值一样,即导航到某个<result>标签指定的视图资源上(拦截器和被配置到的那个action共享一份<result>列表)。说到这里你可能会有疑问,拦截器在action之前执行,而拦截器就会导航到相应的视图资源上,那action中execute方法的返回值不就没啥用了吗,可现实不是这样的啊。这就要说说intercept方法的参数了。ActionInvocation是action的调度者,可以通过它调度该拦截器所属的那个action或者获取该action的引用。ActionInvocation中有一个方法叫invoke(),这个方法就是调用相应action的execute方法,将控制权转移到action中(实际上是把执行的权利交给下一个拦截器,当没有下一个拦截器时,才会执行action的execute方法)。execute方法执行完之后就会根据execute方法的返回值导航到视图资源上。ActionInvocation还有一个重要的方法,叫getAction(),即获取相应action的引用,该方法的返回值类型为Object。获取到引用之后我们就可以通过反射机制进行一些列操作。“自动赋值”的原理就是这样,通过反射机制,根据表单字段名,调用相应的setter方法。这也就解释了为什么要使表单字段名和action属性名一致,且action要有setter方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值