深入struts2拦截器

来源:互联网 发布:linux tomcat配置 编辑:程序博客网 时间:2024/06/05 05:22

         拦截器是Struts2的一个重要的组成部分,可以说拦截器是一个勤劳的幕后工作者,Struts2的大部分功能都有拦截器完成了,也是由于拦截器的使用,使Struts2成为一个非常Clean的框架。你甚至不要在自己的Action中写任何代码,一些重要的功能框架已帮你实现,如将请求参数到Action中属性的传递,系统Local的设置,参数验证等。Strus2提供了大量的拦截器的实现,这些拦截器可以满足绝大不部分需求,我们完全可以复用框架提供的拦截器,而我们仅仅需要做的工作就是简单的几行配置,即可将系统提供的拦截器或自己开发的拦截器应用到自己的系统。而Struts2拦截器的设计使我们很容易使用拦截器,但只有了解拦截器的工作原理,才能真正了解Struts2框架。

        工作原理:Struts2的拦截器的实现原理和过滤器的实现差不多,对你真正想执行的execute()方法进行拦截,然后插入一些自己的逻辑。如果没有拦截器,这些要插入的逻辑就得写在你自己的Action实现中,而且每个Action实现都要写这些功能逻辑,这样的实现非常繁琐。而Struts2的设计者们把这些共有的逻辑独立出来,实现成一个个拦截器,既体现了软件复用的思想,又方便程序员使用。Struts2中提供了大量的拦截器,多个拦截器可以组成一个拦截器栈,系统为我们配置了一个默认的拦截器栈defaultStack,具体包括那些拦截器以及他们的顺序可以在Struts2的开发包的struts-default.xml中找到。在每次对你的Action的execute()方法请求时,系统会生成一个ActionInvocation对象,这个对象保存了action和你所配置的所有的拦截器以及一些状态信息。比如你的应用使用的是defaultStack,系统将会以拦截器栈配置的顺序将每个拦截器包装成一个个InterceptorMapping(包含拦截器名字和对应的拦截器对象)组成一个Iterator保存在ActionInvocation中。在执行ActionInvocation的invoke()方法时会对这个Iterator进行迭代,每次取出一个InterceptorMapping,然后执行对应Interceptor的intercept(ActionInVocationinv)方法,而intercept(ActionInInvocationinv)方法又包含当前的ActionInInvcation对象作为参数,而在每个拦截器中又会调用inv的invoke()方法,这样就会进入下一个拦截器执行了,这样直到最后一个拦截器执行完,然后执行Action的execute()方法(假设你没有配置访问方法,默认执行Action的execute()方法)。在执行完execute()方法取得了result后又以相反的顺序走出拦截器栈,这时可以做些清理工作。最后系统得到了一个result,然后根据result的类型做进一步操作。

       ActionInvocation:这是个非常重要的类,它是Struts2拦截器的核心,它保存了整个拦截器栈信息。了解了ActionInvocation的功能就等于了解了Struts2是怎样处理请求的,所以了解它对我们了解Struts2的执行原理非常重要。当一个请求到来,框架会根据URL从配置文件中得到对应的Action类,然后新建一个Action的实例保存在ActionInvocation中,然后会根据配置得到你的拦截器栈,然后将这些拦截器信息以你配置的顺序添加到ActionInvocation中,ActionInvocation还包含一些其他信息,如result配置等。现在ActionInvocaton已经包含了所有的配置信息,然后就是怎样执行这些拦截器和Action类了,所有的这些步骤从ActionInvocation的invoke()方法开始。Invoke()方法总是取出下一个拦截器来执行。而在拦截器中又会执行ActionInvocation的invoke()方法,这样就会按拦截器配置的顺序执行完所有的拦截器,最后执行Action对应的方法。

          实现自己的拦截器:其实实现自己的拦截器是一个相当容易的事情,我们可以随便打开框架提供的默认实现拦截器的源码看看。比如最简单的LoggingInterceptor,可以得到开发一个拦截器所需要的步骤和所需要注意的问题。首先,我们可以继承AbstractInterceptor类,然后重写父类的Intercept(ActionInvocationinvocation)方法,我们可以看到intercept(ActionInvocationinvocation)方法签名中抛出异常,但我们无需在实现中捕获任何异常,因为框架为我们提供了ExceptionMappingInterceptor来处理这些异常。只要注意一定要在intercept()方法中要调用invocation.invoke()方法 。注意:执行invocation.invoke()逻辑之前执行的代码会在进入拦截器栈时执行,而执行invocation.invoke()逻辑之后的代码会在离开拦截器栈的时候执行。这样,一个拦截器就开发完了,剩下的就是将自己开发的拦截器配置到自己的应用了。

Public class MyInterceptor extendsAbstractInterceptor{

           Public Stringintercept(ActionInvocation invocation) throws Exception{

                    DoSomeThingBeforeGoIntoNextIntercept()

                     String result = invocation.invoke();

                      DoSomeCleanThing();

           }

 

}

配置拦截器:我们可以参考struts-default.xml中拦截器的配置,一个拦截器栈可以包括一系列拦截器,在Strus2中对拦截器配置用<interceptors>节点,而<interceptors>又可以包含<interceptor>和<interceptor-stack>。在struts-2.1.dtd中对拦截器的配置定义:<!ELEMENTinterceptors (interceptor|interceptor-stack)+>,按照配置定义,我们很容易就可以配置好自己的拦截器,在<action>节点中我们可以用<interception-ref/>节点来应用我们配置的拦截器,但是注意:在struts-default.xml中,框架为我们配置了默认的拦截器栈<default-interceptor-refname=”defaultStack”>,如果我们在<action>节点中配置了拦截器,则默认的拦截器则不会起作用,如果该Action需要使用该默认拦截器,则必须将该默认拦截器配上。我们还可以在Struts.xml中配置<default-interceptor-ref>,它会覆盖struts-default.xml中的配置,并在整个<package>中起作用。

原创粉丝点击