Struts 2的拦截器(Interceptor)

概念上讲,Struts 2的拦截器(interceptor) 就是 servlet filter 或 JDK 代理类。你可在业务逻辑执行之前,中间和之後执行拦截器方法。Struts 的很多功能都是通过拦截器实现的,比如:异常处理,文件上传,校验等。

1. Hello, World!

本例以 Struts 2 Hello World 的例子为基础,在其上修改即可。这里略去了 HelloWorldAction 类的代码,其中的 execute() 只是打印"Inside Action!!!"这句话而已。

自定义一个 Interceptor 类:

package org.iridium.hellostruts;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor {
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
               /* let us do some pre-processing */
              String output = "Pre-Processing" ;
              System. out .println(output);
               /* let us call action or next interceptor */
              String result = invocation.invoke();
               /* let us do some post-processing */
              output = "Post-Processing" ;
              System. out .println(output);
               return result;
       }
}

将该 interceptor 加入到 struts.xml 配置中:

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
        <constant name = "struts.devMode" value = "true" />
        <package name = "helloworld" extends = "struts-default">
               <interceptors>
                      <interceptor name = "myinterceptor" class = "org.iridium.hellostruts.MyInterceptor" />
               </interceptors>
               <action name = "hello" class = "org.iridium.hellostruts.HelloWorldAction"
                      method = "execute">
                      <interceptor-ref name = "params" />
                      <!-- <interceptor-ref name="timer" /> -->
                      <interceptor-ref name = "myinterceptor" />
                      <result name = "success"> /HelloWorld.jsp </result >
                      <result name = "error"> /error.html </result >
               </action>
        </package>
</struts>

运行後,每访问一次 hello Action 就可以在 {tomcat home}/logs/catalina.out 中看到如入输出:

Pre-Processing
Inside Action!!!
Post-Processing

注:上面例子中 params 拦截器是 Struts 的一个内建拦截器,用它传递参数。

2. 原理解析

由上面的示例,也可看出,Inteceptor 可以看作一个 Action 的代理类,官方说明中的图很清晰地展现了这种关系:

struts2 interceptor, proxy of action

(图片地址:https://cwiki.apache.org/confluence/download/attachments/13941/overview.png?version=1&modificationDate=1132118952000&api=v2

除了能自定义 interceptor,Struts2 本身在 struts2-core-2.3.16.1.jar/struts-defalut.xml 和 xwork-core-2.3.16.1/xwork-default.xml 中定义大量的 interceptors,实际上,interceptor 是 Struts 的核心之一。

3. Interceptor Stack

在很多 Web 应用中,我们可能多次需要使用同一组 interceptors, 为了书写上的方便,可以将这一系列 interceptors 配置在一起,即所谓的 interceptor stack, 示例如下:

<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>

(注:本例来源于官方文档)

【附】

官方参考:http://struts.apache.org/release/2.3.x/docs/interceptors.html

教程参考:http://www.tutorialspoint.com/struts_2/struts_interceptors.htm