struts2攔截器實現原理案例分析

 

今天學習了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實例作爲目標對象,然後以該目標對象,創建該對象的搭理對象——代理對象裏的方法,是攔截器方法和目標對象方法的組合,這就是爲什麼可以在執行目標方法的前後,執行攔截器方法的原因。

   上面程序執行後的結果:

   

*****通用方法一******

他是一隻小獵狗!

*****通用方法二******

他奔跑迅速!

   

 

發佈了138 篇原創文章 · 獲贊 3 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章