+ 实现 Interceptor 接口  com.opensymphony.xwork2.interceptor. Interceptor,接口定义如下:
 
public   interface   Interceptor  extends  Serializable {
    void  destroy();
    void  init();
    String intercept(ActionInvocation invocation)  throws  Exception;
}
     
     * init():主要在 interceptor 被创建后调用,主要用于初始化一些必要的资源,如:数据库资源等等;
     * destroy():在 interceptor 实例被销毁前调用,主要用于释放一些分配的资源;
     * intercept(ActionInvocation invocation):即为用户需要实现的拦截动作,输入参数为 ActionInvocation,其包含了被拦截的 Action 的引用,可以调用该参数的 invoke 方法,将控制权转给下一个拦截器,或者转给 Action 的 execute 方法;另外,该方法的返回参数是一个与 Action 的 execute 方法一样的 作为 逻辑视图 的字符串,如果该方法直接返回了一个字符串,则会跳转到 逻辑视图 对应 的 实际视图资源,而不会再调用被拦截 的 Action;
      
     通过查看 Interceptor 的 Hierarchy,可以看到系统已经提供了很多的 Interceptor 类:
 
     可以看到绝大部分的 Interceptor 实现类都是继承于 AbstractInterceptor 抽象类的,而该类的 init() 和 destroy() 方法提供的是一个空实现,因此,如果我们实现的拦截器不需要申请资源,则可以无需实现这两个方法。下面通过 LoggingInterceptor 的了解一下 interceptor 的基本实现方式:
 
public   class   LoggingInterceptor  extends  AbstractInterceptor {
     private   static   final   Logger  LOG   = LoggerFactory.getLogger(LoggingInterceptor.  class );
     private   static   final   String  FINISH_MESSAGE   "Finishing execution stack for action " ;
     private   static   final   String  START_MESSAGE   "Starting execution stack for action " ;

     @Override
     public  String intercept(ActionInvocation invocation)  throws  Exception {
        logMessage(invocation,  START_MESSAGE  );
        // 执行该拦截器的下一个拦截器,或者是 Action 的 execute 方法
        String result = invocation.invoke();
        logMessage(invocation,  FINISH_MESSAGE  );
         return  result;
    }

     private   void  logMessage(ActionInvocation invocation, String baseMessage) {
         if  ( LOG   .isInfoEnabled()) {
            StringBuilder message =  new  StringBuilder(baseMessage);
            String namespace = invocation.getProxy().getNamespace();

             if  ((namespace !=  null ) && (namespace.trim().length() > 0)) {
                message.append(namespace).append(   "/"  );
            }

            message.append(invocation.getProxy().getActionName());
             if  ( LOG   .isInfoEnabled()) {
               LOG .info(message.toString());
            }
        }
    }
}
 
     可以看到 LoggingInterceptor 只是简单的在 action 的执行之前和之后输出 INFO 级别的 start 和 finish 日志。
     
     另外,如果需要在拦截器中解析 HTTP 请求或响应等信息,以及将解析的请求中的参数设置给 Action 的属性(其实这是系统 params 拦截器实现的功能),可通过 ServletActionContext 来获取 HTTP 请求或响应:
 
      public  String intercept(ActionInvocation invocation)  throws  Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        String contentType = request.getHeader(   "content-type"  );
 
+ 使用拦截器
 
      < package   name   =  "cdsmc.auth"   extends =  "struts-default" >
          <!-- 拦截器定义 -->
          < interceptors   >
             <!-- 因当前 package 扩展于 struts-default,而在 struts-default.xml 中已经定义了 logger,因此这里使用了 logger-test -->
             < interceptor   name   =  "loggerTest"   class =   "com.opensymphony.xwork2.interceptor.LoggingInterceptor"   />
          </  interceptors >
   
         < action   name   =  "login"   class =  "actionLogin" >
                 < result   name   =  "error"   type =   "redirect"  > /login.jsp  </ result   >
             < result   name   =  "success"   type =   "redirect"  > /user/list.jsp   </  result >
             < interceptor-ref   name   =  "defaultStack" />
             < interceptor-ref   name   =  "loggerTest" />
         </ action   >
     </ package   >
     
     定义了拦截器 loggerTest,并在 login action 中引用了该拦截器,另外,注意到在action中还显式的引用了 defaultStack 拦截器栈,这是因为如果在 action 中指定了一个拦截器,则系统默认的拦截器则会失效。而默认拦截器栈的作用可以参考下面的 struts-default.xml 中对于 defaultStack 的定义。
     
     上面注释提到的,关于使用的 LoggingInterceptor 其实已经在 struts-default.xml 中定义了,而且我们上面看到的 Interceptor 继承结构中的Interceptor实现类都已经在此配置中定义,如下(strut2-core-2.3.4.1):
 
      < package   name   =  "struts-default"   abstract =   "true"  >
        ...

         < interceptors   >
             < interceptor   name   =  "alias"   class =   "com.opensymphony.xwork2.interceptor.AliasInterceptor"   />
             < interceptor   name   =  "autowiring"   class =   "com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"   />
             < interceptor   name   =  "chain"   class =   "com.opensymphony.xwork2.interceptor.ChainingInterceptor"   />
            ......
            <interceptor name = "logger" class= "com.opensymphony.xwork2.interceptor.LoggingInterceptor" />
             < interceptor   name   =  "modelDriven"   class =   "com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"   />
            ......
             < interceptor   name   =  "annotationWorkflow"   class =   "com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"   />
             < interceptor   name   =  "multiselect"   class =   "org.apache.struts2.interceptor.MultiselectInterceptor"   />
                        ......
            <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>
            ... ...

        </ interceptors   >

         < default-interceptor-ref   name   =  "defaultStack" />

         < default-class-ref   class =   "com.opensymphony.xwork2.ActionSupport"   />
     </ package   >
     
     配置完成后测试运行,可看到如下日志:
 
2013-01-12 09:26:59|15715507@qtp-5480883-5|INFO|com.opensymphony.xwork2.interceptor.LoggingInterceptor|Starting execution stack for action //login
2013-01-12 09:26:59|15715507@qtp-5480883-5|DEBUG|com.opensymphony.xwork2.DefaultActionInvocation|Executing action method = null
2013-01-12 09:26:59|15715507@qtp-5480883-5|DEBUG|org.apache.struts2.dispatcher.ServletRedirectResult|Redirecting to  finalLocation /cdsmc/user/list.jsp
2013-01-12 09:26:59|15715507@qtp-5480883-5|INFO|com.opensymphony.xwork2.interceptor.LoggingInterceptor|Finishing execution stack for action //login