Struts2【拦截器】(一)

什么是拦截器


拦截器Interceptor…..拦截器是Struts的概念,它与过滤器是类似的…可以近似于看作是过滤器


为什么我们要使用拦截器


前面在介绍Struts的时候已经讲解过了,Struts为我们实现了很多的功能,比如数据自动封装阿..文件上传功能阿….Struts为我们提供的这些功能都是通过拦截器完成的……


  • 数据自动封装通过<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>这个拦截器。
  • 文件上传通过<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>这个拦截器


拦截器的设计就是基于组件设计的应用


再次回顾拦截器基础


在开始讲解Struts的时候已经说明过了struts-default.xml这个文件,它定义了Struts的所有拦截器。因为我们在启动服务器的时候会自动装载这个文件,因此我们才可以在Action中使用到Struts为我们提供的功能【数据自动封装…文件上传】


在struts-default.xml中定义的拦截器就有32个之多,Struts2为了方便我们对拦截器的引用,提供了拦截器栈的定义。


<interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
            </interceptor-stack>


也就是说:当我们要引用多个拦截器的时候,只要把拦截器都放在栈里头,在外边引用拦截器即可!


值得注意的是:Struts2默认执行的是默认拦截器栈,一旦用户有指定执行哪些拦截器,那么默认的拦截器栈就不会被执行!



自定义拦截器


Struts2允许我们自定义拦截器,这就使我们能够更加灵活地操作Struts2这个框架了!


Struts2提供了Interceptor这个拦截器接口,只要我们实现这个接口,那么这就算是自定义开发拦截器了。


当然啦,大部分时候,我们定义拦截器都是继承AbstractInterceptor这个类….为了学习拦截器的内容,下面就实现Interceptor这个接口了。


编写拦截器类


  • 当实现该接口时,有3个需要我们实现的方法:


public class MyInterceptor implements Interceptor {
    @Override
    public void destroy() {
    }
    @Override
    public void init() {
    }
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        return null;
    }
}


init()和destory()都是和拦截器执行顺序有关的方法,我们现在先不理会….首先来讲解intercept这个方法


/**
     * @param actionInvocation 拦截器的执行状态
     */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        //调用invoke()方法,代表着放行执行下一个拦截器,如果没有拦截器了,那么就执行Action的业务代码
        actionInvocation.invoke();
        return null;
    }


这很容易就能让我们想起在学习过滤器中的doFilter()方法,其实是差不多的!



在struts.xml中配置


像Struts默认的拦截器一样,我们自定义的拦截器是需要我们在struts中配置的。


由于我们配置了自定义拦截器,那么struts默认的拦截器栈是不会执行的。如果我们想要使用默认拦截器栈的功能,就必须把它配置在我们自定义的栈中!


<package name="xxx" extends="struts-default" >
        <interceptors>
            <!--配置用户自定义的拦截器-->
            <interceptor name="MyInterceptor" class="TestAction"/>
            <!--自定义拦截器栈,我们配置了自定义的拦截器,默认的拦截器栈就不会被执行,因此,想要使用默认的拦截器功能,就要配置进来-->
            <interceptor-stack name="mystack">
                <!--引用默认的拦截器栈,一定要放在第一行-->
                <interceptor-ref name="defalutStack"/>
                <!--引用自定义的拦截器-->
                <interceptor-ref name="MyInterceptor"/>
            </interceptor-stack>
        </interceptors>
        <!--上面配置了拦截器栈,但是没有被执行...下面配置执行拦截器-->
        <default-interceptor-ref name="mystack"/>
        <action name="TestAction" class="TestAction" method="execute">
            <result name="success">/index.jsp</result>
        </action>
    </package>


拦截器的执行顺序


我们来观察拦截器和Action类的执行顺序…只要在对应的方法上向控制台输出就行了!


  • 拦截器
public class MyInterceptor implements Interceptor {
    @Override
    public void destroy() {
        System.out.println("我是拦截器的销毁方法");
    }
    @Override
    public void init() {
        System.out.println("我是拦截器的初始化方法");
    }
    /**
     * @param actionInvocation 拦截器的执行状态
     */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("我是拦截器的拦截方法");
        //调用invoke()方法,代表着放行执行下一个拦截器,如果没有拦截器了,那么就执行Action的业务代码
        //可看成是过滤器的doFilter()方法
        actionInvocation.invoke();
        return null;
    }
}
  • Action类
public class TestAction extends ActionSupport {
    public TestAction() {
        System.out.println("我是Action类,我被初始化了!");
    }
    @Override
    public String execute() throws Exception {
        System.out.println("我是Action类的执行方法");
        return null;
    }
}

效果

Struts2【拦截器】(一)这里写图片描述


从效果图我们可以看出,他们的执行顺序是这样的:


  • 当服务器开启的时候,会执行拦截器的init()方法
  • 当访问Action时,Action实例被创建
  • 创建完Action实例,会调用拦截器的interceptor()方法
  • 最后,执行Action的execute()方法


其实很好理解,之前我们使用Struts为我们提供数据自动封装功能的时候,是这样子的:


  • 服务器启动,加载配置文件的信息
  • 初始化默认的拦截器栈
  • 当用户访问Action时,创建Action的实例。拿到Action具体的信息【成员变量、setter和getter】
  • 执行拦截器具体的内容,根据Action具体的信息,把web端的数据封装到Action上
  • 最后在execute()就可以得到封装后的数据了!

Struts2【拦截器】(一)这里写图片描述

上一篇:Linux内核-协议栈-初始化流程分析


下一篇:关于linux内核cpu进程的负载均衡