7.struts2核心-拦截器(interceptor)

7.struts2核心---拦截器(interceptor)
interceptor(拦截器)作为struts2的核心内容,struts2的大部分功能都是靠拦截器来实现的,如:校验,国际化,类型转换。。。

1.拦截器的概念

拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。

在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。

说到拦截器,不得不提下过滤器,其两者原理非常相似,在过滤器里面有过滤器链这个说法,而在Struts 2中称为拦截器栈Interceptor Stack。拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

2.拦截器的实现原理

当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器,这个和过滤器原理相似,从下面的图中可以很容易理解其工作方式。

7.struts2核心-拦截器(interceptor)

3.struts2自带的拦截器

struts2默认提供了十分丰富的拦截器,大家可以在struts2-core-2.3.1.2.jar包中的struts-default.xml查看关于默认的拦截器与拦截器链的配置。

//截取的部分默认拦截器
<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="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
            <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
            <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
            <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
            <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
            <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
            <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
            <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
            <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
            <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
            <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
            <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
            <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
            <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
            <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
            <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
            <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
            <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
            <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
            <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
            <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
            <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
            <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
            <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
            <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
            <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
            <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
            <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
            <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
</interceptors>


4.拦截器的配置

既然struts2自带了这么多拦截器,那么我们该怎么使用呢?下面我将给大家介绍自带拦截器的使用。

<?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>
	<package name="myStruts2" extends="struts-default">
		<action name="login" class="com.hx.struts2.LoginAction">
		    <result name="success">suc.jsp</result>
                    //使用自带的timer拦截器
                    <interceptor-ref name="timer"></interceptor-ref>
		</action>
	</package>
</struts>
/*
注:package 的name属性可以随便取,extends属性值必须是struts-default,如果想让某个Action使用某个拦截器只需在此Action里面加上如上配置即可,<interceptor-ref name="xxx"></interceptor-ref>,这个name属性值和你想要用的自带拦截器name属性值对应即可,要特别注意的是,每个action都有默认的拦截器,你如果加上“<interceptor-ref name="xxx" />”就会覆盖默认的defaultStack。如果你既想使用默认defaultStack,又想使用你想用的如上的<interceptor-ref name="timer"></interceptor-ref>拦截器,该怎么办呢?其实很简单,你只需在action的上面自己建一个拦截器栈即可。方法如下。
*/
<interceptors>
	<interceptor-stack name="myStack">
		<interceptor-ref name="defaultStack"></interceptor-ref>
		<interceptor-ref name="timer"></interceptor-ref>
	</interceptor-stack>
</interceptors>
//现在只需引入<interceptor-ref name="myStack"></interceptor-ref>即可满足你的需求,
//myStack里面可以任意添加自己想要实现的拦截器。


5.自定义拦截器的实现

大家用着用着可能发现使用自带的太局限了,struts2当然也早就考虑到这个问题,所以人家就利用那句话---“约定大于配置”,给你一个约定,你可以按照约定自己编写自己想要的拦截器,下面就给大家介绍该如何编写一个自己的拦截器。

//拦截器分为两种:1>.普通拦截器 2>方法拦截器

//大家在创建拦截器的时候一定要注意:拦截器必须是无状态的,否则可能引起线程同步 !

//1>.普通拦截器
public class MyInterceptor implements Interceptor { 
 
@Override 
public void destroy() { 
  System.out.println("interceptor销毁"); 
} 
 
@Override 
public void init() { 
  System.out.println("interceptor初始化"); 
} 
 
@Override 
public String intercept(ActionInvocation invocation)  
  throws Exception { 
  //验证代码...
  return xxx; 
} 
//如果你不需要init和destroy方法,你可以直接继承AbstractInterceptor

//在action里面配置自定义的拦截器
<interceptors> 
  <interceptor name="myTimer" class="com.kaishengit.interceptor.MyInterceptor">  </interceptor> 
  <interceptor-stack name="myInterceptor"> 
    <interceptor-ref name="myTimer"></interceptor-ref> 
    <interceptor-ref name="defaultStack"></interceptor-ref> 
  </interceptor-stack> 
</interceptors> 


//2>方法拦截器
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

public class MyMethodInterceptor extends MethodFilterInterceptor {

  private static final long serialVersionUID = 1L;

  @Override
  protected String doIntercept(ActionInvocation invocation) throws Exception   {
	
    System.out.println(invocation.getProxy().getMethod() + "interceptor...");
    return invocation.invoke();	

  }

}
//方法拦截器的配置和普通拦截器的一样,方法拦截器还可以自定义拦截哪些方法
<interceptor-ref name="myMethodInterceptor">
    //会拦截的方法
    <param name="includeMethods">login,edit,saveEdit</param>
    //放行的方法
    <param name="excludeMethods">execute,edit</param>
</interceptor-ref>

/*
最后还想给大家说一点技巧,如果你想让每个action都应用某个拦截器或者拦截器栈,为每个action都配置此个拦截器肯定不合理,这时候你可以自定义一个默认的拦截器。注意:默认拦截器一定要放到定义的拦截器的下面,这个struts2的约定!
*/
<default-interceptor-ref name="myStack"></default-interceptor-ref>
/*
另外还有你对用户是否登录的验证时候,没登录的必须让其返回到登录页进行登录,这时你可以配置一个全局的result。
*/
<global-results>
	<result name="error" type="redirectAction">index</result>
</global-results>


好了,对于struts2的拦截器就说到这里,下一篇将给大家说一下struts2的文件上传。