Struts2的拦截器

拦截器(Interceptor)是Struts2的核心组成部分。很多功能(Feature)是构建在拦截器基础上的,例如文件的上传和下载、国际化、转换器和数据校验等,Struts2利用内建的拦截器,完成了框架内的大部分操作。

拦截器动态拦截Action调用的对象,它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者执行之后运行,也可以在一个Action执行之前阻止Action执行。同时也提供了一种可以提取Action中可重用的部分的方式。

在Struts2架构中,可以使用配置文件,灵活配置定义拦截器。当需要一个拦截器的时候,只要在配置文件中设置即可;如果不需要时,可以取消该拦截器,这样就可以实现拦截器同Action类的松耦合,提高系统扩展性。

一、 Struts2拦截器原理
Struts2架构的Action被一个或者多个拦截器(拦截器栈)所包围,所有的用户请求都会被拦截器所拦截,然后交给Action处理,处理结果以逻辑视图方式返回给用户。 这个调用执行流程是由Struts2的配置文件来实现的。 当用户请求到达Struts2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截对象,然后串成一个列表(List),最后一个一个地调用列表中的拦截器。
二、 定义拦截器

Struts2框架的拦截器处理机制采用了AOP(面向方面编程)设计思想。使得拦截器(拦截器组)可以类似“热插拔”的方式来组合,配合业务控制器Action来完成用户请求的处理。 这种“热插拔”实际上是通过Struts2框架的配置文件来实现的,配置文件中可以定义拦截器和拦截器栈,并可以在Action中定义所使用的拦截器或者拦截器栈。开发者如果要改变拦截器的执行顺序或者数量,只需要修改配置文件即可。

在struts.xml配置文件中,配置拦截器如下:

<interceptors>
	<!--定义拦截器-->
	<interceptor  class="intercept.FilterInterceptor"  
		  name="filterIntercept"></interceptor>
	<interceptor class="interceptOrder.InterceptorOrder"
		   name="InterceptorOrder">
		<!--定义拦截器参数-->
		<param name="">value</param>
		<param name="">value</param>
	</interceptor>
	<interceptor name="checkIntercept" 
		class="authorityIntercept.CheckInterceptor">
	</interceptor>
	<!--定义拦截器栈-->
	<interceptor-stack name="myDefaultStack">
		<interceptor-ref name="defaultStack"></interceptor-ref>
		<interceptor-ref name="checkIntercept"></interceptor-ref>
	</interceptor-stack>
</interceptors>

三、 使用拦截器
  1、在Struts2框架中定义了拦截器或者拦截器栈,就可以在配置文件中使用该拦截器或者拦截器栈来拦截Action。指定拦截器或者拦截器栈,会在Action的execute()方法执行之前被执行。Action中配置拦截器如下:
<action name="FilterAction" class="intercept.FilterAction">
	<result name="success">/intercept/MethodFilter.jsp</result>
	<!--显式引用默认拦截器-->
	<interceptor-ref name="defaultStack"></interceptor-ref>  
	<!--自定义拦截器栈-->
	<interceptor-ref name="myDefaultStack">
	</interceptorref>           
	<interceptor-ref name="filterIntercept">
	<!--在使用拦截器时指定拦截器参数-->
		<param name="includeMethods">method1</param>
		<param name="excludeMethods">method2</param>
		<param name="name">方法过滤拦截器</param>
	</interceptor-ref>         
</action>

 注意:Struts2框架的默认拦截器defaultStack包含了很多重要的功能,在Action定

             义自己的拦截器的同时,一定要注意需要同时显式的引用系统默认拦截器

                    defaultStack。

  2、 配置默认拦截器

为了避免每个Action配置相同的拦截器,使用默认拦截器,则包内所有Action都会自动使用默认拦截器,避免了配置代码的重复使用。

配置默认拦截器使用<default-interceptor-ref…/>元素,该元素为包<package…/>的一个子元素,如果在包配置中定义了一个默认拦截器,那么该拦截器对包内所有的Action都是有效的,Action中显式定义拦截器情况下除外。

<default-interceptor-ref…/>元素需要指定一个name属性,该属性指定默认拦截器的名称。该属性必须是一个已经存在的拦截器名称,即前面已经定义好了的。

<interceptors>
	<interceptor name="checkInterceptor" class="bbs.checkInterceptor"></interceptor>
	<interceptor-stack name="bbsStack">
		<interceptor-ref name="defaultStack"></interceptor-ref>
		<interceptor-ref name="checkInterceptor" />
		<interceptor-ref name="jsfStack" />
	</interceptor-stack>
</interceptors>
<!--指定包内默认拦截器-->
<default-interceptor-ref name="bbsStack"></default-interceptor-ref>

注意:在指定包内默认拦截器时,只能使用一个<default-interceptor-ref…/>元素,即每个包内只能定义一个默认的拦截器。 如果需要将多个拦截器都设置为一个包的默认拦截器,最好的方式是将这些拦截器组成一个拦截器栈,再将拦截器栈设置为包的默认拦截器。

3、 自定义拦截器实现类

a、 Struts2框架为开发者自定义拦截器实现类提供了一个Interceptor接口,用户可

        以实现该接口来开发自定义拦截器实现类。Interceptor接口中定义了三个方法:

            init()、destroy()和String interceptor(ActionInvocation invocation)。

b、 Struts2框架除了提供Interceptor接口用于开发自定义拦截器实现类外,还提供

        了一个com.opensymphony.xwork.interceptor.AbstractInterceptor 类,

        开发者只要继承该类,就可以用简单的方式来实现自己的拦截器实现类。该类实

        现了Interceptor接口。 该类同样定义了上面的三个方法,如果在用户自定义的

        拦截器实现类的初始化时,不需要加载一些特殊的系统资源,可以不用实现init()

        和destroy()方法。只需要重写interceptor(ActionInvocation invocation)方

        法即可。

四、 拦截器深度剖析

1、 拦截器的方法过滤

业务控制器Action中可以使用动态方法来处理用户请求,这样Struts2框架的Action更加灵活。 在Action中使用拦截器,默认情况下会拦截Action实现类中的所有方法。但是某些情况下,开发者可能只需要拦截Action中的一个或者多个方法,有时候也希望拦截器不拦截某些Action方法。 这时,让拦截器有选择的拦截Action中的某个方法,就需要使用拦截器的方法过滤。

Struts2框架提供了一个MethodFilterInterceptor类,开发者自定义的拦截器只要继承该类,就可以使用拦截器的方法过滤功能,来拦截Action中特定的方法。

MethodFilterInterceptor类为

com.opensymphony.xwork.interceptor.AbstractInterceptor拦截器类的子类,实现了Interceptor和Serializable接口。该类有两个重要的参数:

excludeMethods:该参数指定拦截器拒绝拦截的方法列表。多个方法值中间用逗号分开。

        includeMethods: 该参数指定拦截器需要拦截的方法列表。多个方法值中间用逗号分开。

下面给出该类的主要方法:

        protected abstract String doInterceptor(ActionInvocation invocation) :继承该类的子类必须重写该方法,并实现拦截器逻辑。

        String interceptor(ActionInvocation invocation):继承自AbstractInterceptor类,该方法不需要强制重写。

        void setExcludeMethods(String excludeMethods):设置黑名单,该方法参数为一个字符串,即对应的Action方法名称。

        void setIncludeMethods(String includeMethods):设置拦截器的白名单。

        Set getExcludeMethodsSet():获得拦截器的黑名单。

        Set getIncludeMethodsSet(): 获得拦截器的白名单。

        注意: 开发者使用MethodFilterInterceptor类的子类来实现拦截器的方法过滤,只需要重写doInterceptor(ActionInvocation invocation)方法即可。

       下面为实现方法过滤拦截的配置文件: filterInterceptor过滤器继承了MethodFilterInterceptor类。

<interceptor-ref name="filterIntercept">
	<!--使用方法过滤,设置白名单或黑名单-->
	<param name="includeMethods">method1</param>
	<param name="excludeMethods">method2</param>
	<param name="name">方法过滤拦截器</param>
</interceptor-ref>  

2、 拦截器的执行顺序

         配置在前面的拦截器,会在被拦截方法执行之前执行拦截动作,拦截器的拦截动作是按照配置文件拦截器的引用顺序来执行的。

3、 拦截结果监听器

        开发者如果需要在Action执行之后,拦截器的interceptor(ActionInvocation arg0)返回result之前进行一些业务处理操作。例如Action执行execute()后,返回一个“success”字符串,拦截器对该返回结果进行处理,修改某些业务数据后,再返回“success”逻辑视图。

a、 实现上面的要求,可以在拦截器的invoke()方法之后加入处理代码。例如:

public String intercept(ActionInvocation arg0) throws Exception {
	//注册一个监听器
	arg0.addPreResultListener(new MyListener());
	System.out.println(name+"拦截器信息:启动拦截器,拦截Action时间:"+new Date());
	String result=arg0.invoke();
	//根据处理结果处理其他业务
	if(result.equals("success")){
		dosomething();
	}
	System.out.println(name+"拦截器信息:Action执行完毕时间:"+new Date());
		return result;
}

b、上面代码会导致拦截器中加入了大量的业务逻辑判断和处理代码,从而降低了系统代码的复用性。 为了处理Action执行处理方法之后和拦截器返回result之间节点的业务,Struts2框架提供了一个PreResultListener接口。实现该接口就可以监听Action特定方法执行之后的结果,并做进一步的预后处理。

PreResultListener接口中只有一个方法,如下所示。该方法中有两个参数,其中resultcode就是Action执行之后返回的结果。

 void beforeResult(ActionInvocation invocation, String resultcode)

i. 开发者可以开发自己的监听器类,该类必须实现PreResultListener接口,并重写void beforeResult(ActionInvocation invocation, String resultcode)方法。例如下面的代码:

public class MyListener implements PreResultListener {
	public void beforeResult(ActionInvocation arg0, String arg1) {
	  // TODO Auto-generated method stub
	  System.out.println("监听器监听执行结果..."+arg1);
	}
}

ii. 为了使用监听器,需要在拦截器中注册监听器。下面的示例中在拦截器中加入了监听器:
public String intercept(ActionInvocation arg0) throws Exception {
	//注册一个监听器
	arg0.addPreResultListener(new MyListener());
	System.out.println(name+"拦截器信息:启动拦截器,拦截Action时间:"+new Date());
	String result=arg0.invoke();
	System.out.println(name+"拦截器信息:Action执行完毕时间:"+new Date());
	return result;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值