Chinese To English     英文 轉 中文             
                   
          隨筆-27  評論-53  文章-0  trackbacks-0

                  大家都知道,在實際應用開發中都會用到數據庫。要用數據庫我們就必須和數據取得連接,否則一切都是空談,我想這個沒有什么好多說的。正因如此問題就出來了,和數據庫取得連接是比較耗資源,而一個網站每天的訪問量也是驚人的,想一想如果客戶端每向服務器發送一個請求服器就要進行打開連接和關閉連接的工作,這樣做明顯是不合理,在實際開發中如果是這樣去實現數據的持久化真是不可思議。所以引入了連接池的概念,所謂連接池就是當用完一個連接后不是將連接直接關閉而是將它放入到一個容器中緩存放起來,下次再用的時候就直接在容器中取,從而初實現連接的重用。

          1:連接池實現類

            1package net.vicp.jiasoft.dpcp.connectionpool;
            2
            3import java.sql.Connection;
            4import java.sql.DriverManager;
            5import java.sql.SQLException;
            6import java.util.Vector;
            7import net.vicp.jiasoft.dpcp.dynaproxy.ConnectionProxy;
            8import net.vicp.jiasoft.dpcp.util.PropertiesUtil;
            9
           10/**
           11 * @author Jak.Shen
           12 * 日期:2008-3-31
           13 * 說明:連接池實現類
           14 */

           15
           16public class ConnectionPool {
           17
           18    private static ConnectionPool connectionPool;//自身靜態成員變量,用于實現單例.
           19    private static Vector connPool;//連接緩存容器
           20    private int poolMaxSize = 10;//連接池最大緩存數
           21    private String userName;//連接用戶名
           22    private String password;//連接密碼
           23    private String driverClass;//連接驅動
           24    private String url;//連接字符串
           25
           26    /**
           27     * 私有構造方法,初始化變量.并心預填充連接池。
           28     */

           29    private ConnectionPool() {
           30        String temp = PropertiesUtil.getValueByKey("poolMaxSize");
           31        if (temp != null{
           32            poolMaxSize = Integer.parseInt(temp);
           33        }

           34        userName = PropertiesUtil.getValueByKey("userName");
           35        password = PropertiesUtil.getValueByKey("password");
           36        driverClass = PropertiesUtil.getValueByKey("driverClass");
           37        url = PropertiesUtil.getValueByKey("url");
           38        connPool = new Vector();
           39        int size = 0;
           40        if (poolMaxSize > 5{
           41            size = 5;
           42        }
           else {
           43            size = poolMaxSize;
           44        }

           45        for (int i = 0; i < size; i++{
           46            connPool.add(createConnection());//預填充連接池
           47        }

           48    }

           49
           50    /**
           51     * 此方法用于創建并返回連接池對象。
           52     * @return
           53     */

           54    public static ConnectionPool newInstance() {
           55        if (connectionPool == null{
           56            connectionPool = new ConnectionPool();
           57        }

           58        return connectionPool;
           59    }

           60
           61    /**
           62     * 此方法用于創建一個連接。
           63     * @return
           64     */

           65    private Connection createConnection() {
           66        Connection connection = null;
           67        try {
           68            Class.forName(driverClass);
           69        }
           catch (ClassNotFoundException e) {
           70            e.printStackTrace();
           71        }

           72        try {
           73            connection = DriverManager.getConnection(url, userName, password);
           74        }
           catch (SQLException e) {
           75            e.printStackTrace();
           76        }

           77        return connection;
           78    }

           79
           80    /**
           81     * 此方法用于將用完的連接放入池中。
           82     */

           83    public static synchronized void releaseConnection(Connection connection) {
           84        connPool.add(connection);
           85    }

           86
           87    /**
           88     * 此方法用于返回一個連接。
           89     * @return
           90     */

           91    public synchronized Connection getConnection() {
           92        // 要防止直接關閉連接因此需要對Connection的close()方法進行攔截
           93        // 所以需要要給Connection接口動態加入代理,getConnection()是加入代理的好地方法
           94        // connectionProxy是動態代理對象
           95        ConnectionProxy connectionProxy = new ConnectionProxy();
           96        int size = connPool.size();
           97        if (connPool.size() == 0 || size < poolMaxSize) {
           98            connectionProxy.setConnection(createConnection());
           99            return connectionProxy.proxyBind();
          100        }

          101        Connection connection = (Connection) connPool.get(size - 1);
          102        connectionProxy.setConnection(connection);
          103        connPool.remove(size - 1);
          104        return connectionProxy.proxyBind();
          105    }

          106}

          107

          2:動態代理類
           1package net.vicp.jiasoft.dpcp.dynaproxy;
           2
           3import java.lang.reflect.InvocationHandler;
           4import java.lang.reflect.Method;
           5import java.lang.reflect.Proxy;
           6import java.sql.Connection;
           7import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
           8
           9/** 
          10 * @author Jak.Shen
          11 * 日期:2008-3-31
          12 * 說明:動態代理實類,實現InvocationHandler接口就可以成為動態代理了.要注意的是只能對接口代理。
          13 */

          14 
          15public class ConnectionProxy implements InvocationHandler {
          16
          17    private Connection connection;//動態代理的對象
          18
          19    public ConnectionProxy() {
          20    }

          21
          22    public ConnectionProxy(Connection connection) {
          23        this.connection = connection;
          24    }

          25
          26    /**
          27     * 重寫實現InvocationHandler方法invoke()。
          28     * 此處注意@Override標注在JDK1.6中才支持,JDK1.6以下版本請將@Override標注去掉。
          29     */

          30    @Override
          31    public Object invoke(Object proxy, Method method, Object[] args)
          32            throws Throwable {
          33        // 如果方法是close(),就替換成連接池的releaseConnection()方法.
          34        if (method.getName().equals("close")) {
          35            System.out.println("before invoke !");
          36            ConnectionPool.releaseConnection(connection);
          37            System.out.println("after invoke !");
          38        }
           else {
          39            // 對非close()方法,不做處理,直接調用.
          40            return method.invoke(connection, args);
          41        }

          42        return null;
          43    }

          44
          45    /**
          46     * 綁定要進行代理的對象
          47     * @return
          48     */

          49    public Connection proxyBind() {
          50        // 返回一個指定接口的代理類實例
          51        // newProxyInstance() arg0-->定義代理類的類加載器
          52        // newProxyInstance() arg1-->代理類要實現的接口列表
          53        // newProxyInstance() arg2-->指派方法調用的調用處理程序(此處就是去調用this對象的invoke())
          54        Connection proxyConnection = (Connection) Proxy.newProxyInstance(
          55                connection.getClass().getClassLoader(), connection.getClass()
          56                        .getInterfaces(), this);
          57        return proxyConnection;
          58    }

          59
          60    public Connection getConnection() {
          61        return connection;
          62    }

          63
          64    public void setConnection(Connection connection) {
          65        this.connection = connection;
          66    }

          67}

          68

          3:屬性文件操作工具類
           1package net.vicp.jiasoft.dpcp.util;
           2
           3import java.io.FileInputStream;
           4import java.io.FileNotFoundException;
           5import java.io.IOException;
           6import java.util.Properties;
           7
           8/** 
           9 * @author Jak.Shen
          10 * 日期:2008-3-31
          11 * 說明:屬性文件操作工具類
          12 */

          13
          14public class PropertiesUtil {
          15    private static Properties properties = new Properties();
          16    private static FileInputStream fileInputStream;
          17
          18    /**
          19     * 從屬性文件中根據Key取值
          20     * @param key
          21     * @return
          22     */

          23    public static String getValueByKey(String key) {
          24        if (fileInputStream == null{
          25            try {
          26                fileInputStream = new FileInputStream("src/dpcp.properties");
          27            }
           catch (FileNotFoundException e) {
          28                e.printStackTrace();
          29            }

          30        }

          31        try {
          32            properties.load(fileInputStream);
          33        }
           catch (IOException e) {
          34            e.printStackTrace();
          35        }

          36        return properties.get(key).toString();
          37    }

          38}

          39

          4:測試客戶端
           1package net.vicp.jiasoft.dpcp.client;
           2
           3import java.sql.Connection;
           4import java.sql.SQLException;
           5import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
           6
           7/** 
           8 * @author Jak.Shen
           9 * 日期:2008-3-31
          10 * 說明:動態代理連接池測試客戶端
          11 */

          12public class DbPoolClient {
          13
          14    public static void main(String[] args) {
          15        ConnectionPool connectionPool = ConnectionPool.newInstance();
          16        Connection connection = connectionPool.getConnection();
          17        try {
          18            connection.close();
          19        }
           catch (SQLException e) {
          20            e.printStackTrace();
          21        }

          22    }

          23}

          24

          5:屬性配置文件(dpcp.properties)
           1#最大連接數
           2poolMaxSize=4
           3#連接用戶名
           4userName=scott
           5#連接密碼
           6password=tiger
           7#連接驅動
           8driverClass=oracle.jdbc.driver.OracleDriver
           9#連接字符串
          10url=jdbc:oracle:thin:@localhost:1521:ACCP

          源碼下載 -- (ConnectionPool.rar)

          杰森 
          郵箱:json.shen(at)gmail.com
          網站:www.shenjia.org
          posted on 2008-03-31 18:17 杰森 閱讀(2449) 評論(2)  編輯  收藏 所屬分類: JavaSE

          評論:
          # re: Java實現簡單動態代理連接池 2008-04-18 10:33 | YangYang
          寫的很好,學習了。 msn:seeblue1981@hotmail.com  回復  更多評論
            
          # re: Java實現簡單動態代理連接池 2008-04-18 16:53 | Jak.Shen
          @YangYang
          多謝支持!  回復  更多評論
            
          嗨117
          主站蜘蛛池模板: 财经| 咸丰县| 钟祥市| 龙里县| 米脂县| 上林县| 平乐县| 北票市| 万全县| 三原县| 大悟县| 宣汉县| 陕西省| 舒城县| 临夏县| 侯马市| 浑源县| 惠水县| 临泽县| 大宁县| 木里| 阿鲁科尔沁旗| 专栏| 城固县| 上饶市| 司法| 永善县| 长岭县| 云阳县| 天台县| 安西县| 崇仁县| 中西区| 工布江达县| 清原| 泰州市| 南投市| 东平县| 清涧县| 抚宁县| 阳泉市|