您的位置:首页 > 编程语言 > Java开发

struts2拦截器实现原理案例分析

2012-03-07 22:28 387 查看
今天学习了struts2的拦截器的相关知识。下面是自己自定义的一个拦截器的实现原理。下面为大家解析一下编写一个自定义拦截器原理的步骤及代码。

大部分时候,拦截器方法都是通过代理的方式来调用的,下面以JDK动态代理为例来介绍如何调用拦截器方法。

第一步:

首先要定义一个简单的Dog接口,因为JDK动态代理只能对实现了接口的实例来生成代理,因此必须提供一个Dog接口,该接口代码非常简单。在接口中要定义两个简单的方法。

public interface Dog {
//狗的信息
public void info();
//狗跑
public void run();
}

第二步:

在以上接口中,并没有实现其方法,为了能正常使用Dog实例,必须要提供一个该接口的实现类。实现类的代码:如下:

public class DogImpl implements Dog{
public void info() {
//info方法实现,仅仅打印一个字符串
System.out.println("他是一只小猎狗!");
}
public void run() {
// run方法实现,仅仅打印一个字符串
System.out.println("他奔跑迅速!");
}
}
第三步:

下面就来编写一个拦截Dog实例的拦截器。

系统用于拦截Dog实例的拦截器类如下:

public class DogInterceptor {
//第一个拦截器的方法
public void log(){
System.out.println("*****通用方法一******");
}
//第二个拦截器的方法
public void safe(){
System.out.println("*****通用方法二******");
}
}

通过以上的拦截器,它也是一个普通的java类。假设我们需要上面的info方法执行前后分别调用拦截器里的方法,系统应该如何来实现呢?关键是要编写ProxyHandler类。该类需要实现InvocationHandler接口,该接口是JDK反射体系里的一个接口,它可以动态调用目标对象的方法。

ProxyHandler类的代码如下:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class ProxyHandler implements InvocationHandler{

//需要声明被代理的目标对象

private Object target;

//创建一个拦截器的实例

DogInterceptor dogInterceptor = new DogInterceptor();

//执行代理目标方法的时候,该invoke被自动调用

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object result = null;

//proxy

//method方法

if(method.getName().equals("info")){

dogInterceptor.log();

result = method.invoke(target, args);

dogInterceptor.safe();

}else{

result = method.invoke(target, args);

}

//args方法参数

return result;

}

public Object getTarget() {

return target;

}

public void setTarget(Object target) {

this.target = target;

}

}

第四步:

通过ProxyHandler的帮助,系统实现了在执行info方法之前,调用拦截器的method方法:在指定info方法之后,调用拦截器的run方法。

只因为上面类与被拦截对象没有丝毫耦合,从而提供了更好解耦,以及更好的可扩展性。但上面的类与两个地方耦合了:

(1) 与拦截器类耦合:上面类固定使用DogIntercepter拦截器。

(2) 与被拦截器的方法耦合:上面类指定拦截名为info的方法。

系统还需要提供一个代理工厂,代理工厂的主要作用就是根据目标对象生成一个代理对象。

下面就是一个代理工厂类的代码:

package cn.csdn.hr.jdk.inter;

import java.lang.reflect.Proxy;

//根据目标对象 产生代理对象
public class MyProxyFactory {
public static Object getProxy(Object target){
//创建代理类的处理类
ProxyHandler proxyHandler = new ProxyHandler();
//传递目标对象 到代理对象中
proxyHandler.setTarget(target);
return Proxy.newProxyInstance(DogImpl.class.getClassLoader(),target.getClass().getInterfaces(),proxyHandler);
}
}

第五步:

通过这种方式,实现了在目标方法之前或者之后,自动调用拦截器方法的目的。

下面是测试的方法,代码如下:

public class DogTest {
public static void main(String[] args){
Dog targetDog = new DogImpl();
Object proxy = MyProxyFactory.getProxy(targetDog);
Dog dog = null;
if(proxy instanceof Dog){
dog = (Dog) proxy;
}
if(dog != null){
dog.info();
dog.run();
}
}
}

第六步:

上面的代码先是创建了一个Dog实例作为目标对象,然后以该目标对象,创建该对象的搭理对象——代理对象里的方法,是拦截器方法和目标对象方法的组合,这就是为什么可以在执行目标方法的前后,执行拦截器方法的原因。

上面程序执行后的结果:

*****通用方法一******
他是一只小猎狗!
*****通用方法二******
他奔跑迅速!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: