说说对Struts 2拦截器的理解?

理解拦截器

    拦截器可以动态地拦截发送到指定Action的请求,通过拦截器机制,我们可以在Action执行的前后插入某些代码。通过这种方式,久可以把多个Action中需要重复指定的代码提取出来,放在拦截器里面定义,从而提供更好的代码重用性。拦截器机制是一种非常灵活的软件服用方式。

 

拦截器的实现原理

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

    下面是一个简单的Dog接口,因为JDK动态代理只能对实现了接口的实例来生成代理,因此必须提供一个Dog接口,该接口代码非常简单。

 

1、接口代码

package cn.cdi.intercepter;

public interface Dog {
 //info方法声明
 public void info();
 //run方法声明
 public void run();
}


2、下面提供接口的实现

package cn.cdi.intercepter;

public class DogImpl implements Dog {
 //info方法的实现,仅仅打印一个字符串
 public void info() {
  System.out.println("我是一条狗");
 }
 //run方法的实现,仅仅打印一个字符串
 public void run() {
  System.out.println("我奔跑迅速");
 }
}

 

3、拦截器类

package cn.cdi.intercepter;

public class DogIntercepter {
 //第一个拦截器方法
 public void method1() {
  System.out.println("=====模拟通用方法=====");
 }
 //第二个拦截器方法
 public void method2() {
  System.out.println("=====模拟通用方法=====");
 }
}


4、假如我们需呀上面的info方法执行前后分别调用拦截器里的方法,系统应该如何实现呢?关键定义一个ProxyHandler类。该类需要实现InvocationHandler接口,该接口是JDK反射体系里的一个接口,他是一个可以动态调用目标对象的方法。

package cn.cdi.intercepter;

import java.lang.reflect.InvocationHandler;

public class ProxyHandler implements InvocationHandler{
 //需被代理的目标对象
 private Object target;
 //创建拦截器实例
 DogIntercepter di = new DogIntercepter();
 //执行代理的目标方法时,该invoke方法会被自动调用
 public Object invoke(Objectproxy,java.lang.reflect.Method method,Object[] args) throwsException {
  Object[] result = null;
  //如果被调用方法的方法名为info
  if(method.getName().equals("info")){
   //调用拦截器方法1
   di.method1();
   result =(Object[]) method.invoke(target, args);
   //调用拦截器方法2
   di.method2();
  }else {
   result =(Object[]) method.invoke(target, args);
  }
  return result;
 }
 //用于设置传入目标对象的方法
 public void setTarget(Object o) {
  this.target = o;
 }
}
5、还需要提供一个代理工厂,代理工程的主要作用就是更具目标对象生成一个代理对象:

package cn.cdi.intercepter;

import java.lang.reflect.Proxy;

public class MyProxyFactory {
 public static Object getProxy(Object object){
  //代理的处理类
  ProxyHandler handler = newProxyHandler();
  //把该Dog实例托付给代理操作
  handler.setTarget(object);
  //第一个参数是用来创建动态代理的ClassLoader对象
  //只要该对象能访问Dog接口即可
  //第二个参数是接口数组,正是代理该接口的数组
  //第三个参数是代理包含的处理实例
  returnProxy.newProxyInstance(DogImpl.class.getClassLoader(),object.getClass().getInterfaces(), handler);
 }
}
代理工程里有行代码:

Proxy.newProxyInstance(DogImpl.class.getClassLoader(),object.getClass().getInterfaces(), handler);

    Proxy.newProxyInstance()方法根据接口数组动态创建代理类实例,接口数组通过object.getClass().getInterfaces(),方法获取,创建代理类是JVM在内存中动态创建,该类实现传入参数里接口数组中的全部接口。因此,DynamicProxy要求被代理的必须是接口的实现类,否则无法为其构造相应的动态实例。

   从上面的介绍可以看出,代理工程负责根据目标对象和对应的拦截器生成新的代理对象,代理对象里的方法是目标方法和拦截器方法的组合。正是通过这种方式,实现了在目标方法之前或者之后,自动调用拦截器方法。

 

6、运行主程序

package cn.cdi.intercepter;

public class TestDog {
 public static void main(String[] args) {
  //创建一个Dog实例,该实例将被作为代理的目标对象
  Dog targetObject = newDogImpl();
  Dog dog = null;
  //以目标对象创建代理
  Object proxy =MyProxyFactory.getProxy(targetObject);
  if(proxy instanceof Dog){
   dog = (Dog)proxy;
  }
  //测试代理的方法
  dog.info();
  dog.run();
 }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值