大家都知道,在實際應用開發中都會用到數據庫。要用數據庫我們就必須和數據取得連接,否則一切都是空談,我想這個沒有什么好多說的。正因如此問題就出來了,和數據庫取得連接是比較耗資源,而一個網站每天的訪問量也是驚人的,想一想如果客戶端每向服務器發送一個請求服器就要進行打開連接和關閉連接的工作,這樣做明顯是不合理,在實際開發中如果是這樣去實現數據的持久化真是不可思議。所以引入了連接池的概念,所謂連接池就是當用完一個連接后不是將連接直接關閉而是將它放入到一個容器中緩存放起來,下次再用的時候就直接在容器中取,從而初實現連接的重用。
1:連接池實現類
1
package net.vicp.jiasoft.dpcp.connectionpool;
2
3
import java.sql.Connection;
4
import java.sql.DriverManager;
5
import java.sql.SQLException;
6
import java.util.Vector;
7
import net.vicp.jiasoft.dpcp.dynaproxy.ConnectionProxy;
8
import net.vicp.jiasoft.dpcp.util.PropertiesUtil;
9
10
/** *//**
11
* @author Jak.Shen
12
* 日期:2008-3-31
13
* 說明:連接池實現類
14
*/
15
16
public 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:動態代理類
1
package net.vicp.jiasoft.dpcp.dynaproxy;
2
3
import java.lang.reflect.InvocationHandler;
4
import java.lang.reflect.Method;
5
import java.lang.reflect.Proxy;
6
import java.sql.Connection;
7
import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
8
9
/** *//**
10
* @author Jak.Shen
11
* 日期:2008-3-31
12
* 說明:動態代理實類,實現InvocationHandler接口就可以成為動態代理了.要注意的是只能對接口代理。
13
*/
14
15
public 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:屬性文件操作工具類
1
package net.vicp.jiasoft.dpcp.util;
2
3
import java.io.FileInputStream;
4
import java.io.FileNotFoundException;
5
import java.io.IOException;
6
import java.util.Properties;
7
8
/** *//**
9
* @author Jak.Shen
10
* 日期:2008-3-31
11
* 說明:屬性文件操作工具類
12
*/
13
14
public 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:測試客戶端
1
package net.vicp.jiasoft.dpcp.client;
2
3
import java.sql.Connection;
4
import java.sql.SQLException;
5
import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
6
7
/** *//**
8
* @author Jak.Shen
9
* 日期:2008-3-31
10
* 說明:動態代理連接池測試客戶端
11
*/
12
public 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
#最大連接數
2
poolMaxSize=4
3
#連接用戶名
4
userName=scott
5
#連接密碼
6
password=tiger
7
#連接驅動
8
driverClass=oracle.jdbc.driver.OracleDriver
9
#連接字符串
10
url=jdbc:oracle:thin:@localhost:1521:ACCP
源碼下載 -- (ConnectionPool.rar)
杰森
郵箱:json.shen(at)gmail.com
網站:www.shenjia.org
posted on 2008-03-31 18:17
杰森 閱讀(2440)
評論(2) 編輯 收藏 所屬分類:
JavaSE