大家都知道,在實(shí)際應(yīng)用開發(fā)中都會(huì)用到數(shù)據(jù)庫(kù)。要用數(shù)據(jù)庫(kù)我們就必須和數(shù)據(jù)取得連接,否則一切都是空談,我想這個(gè)沒有什么好多說(shuō)的。正因如此問題就出來(lái)了,和數(shù)據(jù)庫(kù)取得連接是比較耗資源,而一個(gè)網(wǎng)站每天的訪問量也是驚人的,想一想如果客戶端每向服務(wù)器發(fā)送一個(gè)請(qǐng)求服器就要進(jìn)行打開連接和關(guān)閉連接的工作,這樣做明顯是不合理,在實(shí)際開發(fā)中如果是這樣去實(shí)現(xiàn)數(shù)據(jù)的持久化真是不可思議。所以引入了連接池的概念,所謂連接池就是當(dāng)用完一個(gè)連接后不是將連接直接關(guān)閉而是將它放入到一個(gè)容器中緩存放起來(lái),下次再用的時(shí)候就直接在容器中取,從而初實(shí)現(xiàn)連接的重用。
1:連接池實(shí)現(xiàn)類
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
* 說(shuō)明:連接池實(shí)現(xiàn)類
14
*/
15
16
public class ConnectionPool {
17
18
private static ConnectionPool connectionPool;//自身靜態(tài)成員變量,用于實(shí)現(xiàn)單例.
19
private static Vector connPool;//連接緩存容器
20
private int poolMaxSize = 10;//連接池最大緩存數(shù)
21
private String userName;//連接用戶名
22
private String password;//連接密碼
23
private String driverClass;//連接驅(qū)動(dòng)
24
private String url;//連接字符串
25
26
/**
27
* 私有構(gòu)造方法,初始化變量.并心預(yù)填充連接池。
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());//預(yù)填充連接池
47
}
48
}
49
50
/**
51
* 此方法用于創(chuàng)建并返回連接池對(duì)象。
52
* @return
53
*/
54
public static ConnectionPool newInstance() {
55
if (connectionPool == null) {
56
connectionPool = new ConnectionPool();
57
}
58
return connectionPool;
59
}
60
61
/**
62
* 此方法用于創(chuàng)建一個(gè)連接。
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
* 此方法用于返回一個(gè)連接。
89
* @return
90
*/
91
public synchronized Connection getConnection() {
92
// 要防止直接關(guān)閉連接因此需要對(duì)Connection的close()方法進(jìn)行攔截
93
// 所以需要要給Connection接口動(dòng)態(tài)加入代理,getConnection()是加入代理的好地方法
94
// connectionProxy是動(dòng)態(tài)代理對(duì)象
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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

2:動(dòng)態(tài)代理類
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
* 說(shuō)明:動(dòng)態(tài)代理實(shí)類,實(shí)現(xiàn)InvocationHandler接口就可以成為動(dòng)態(tài)代理了.要注意的是只能對(duì)接口代理。
13
*/
14
15
public class ConnectionProxy implements InvocationHandler {
16
17
private Connection connection;//動(dòng)態(tài)代理的對(duì)象
18
19
public ConnectionProxy() {
20
}
21
22
public ConnectionProxy(Connection connection) {
23
this.connection = connection;
24
}
25
26
/**
27
* 重寫實(shí)現(xiàn)InvocationHandler方法invoke()。
28
* 此處注意@Override標(biāo)注在JDK1.6中才支持,JDK1.6以下版本請(qǐng)將@Override標(biāo)注去掉。
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
// 對(duì)非close()方法,不做處理,直接調(diào)用.
40
return method.invoke(connection, args);
41
}
42
return null;
43
}
44
45
/**
46
* 綁定要進(jìn)行代理的對(duì)象
47
* @return
48
*/
49
public Connection proxyBind() {
50
// 返回一個(gè)指定接口的代理類實(shí)例
51
// newProxyInstance() arg0-->定義代理類的類加載器
52
// newProxyInstance() arg1-->代理類要實(shí)現(xiàn)的接口列表
53
// newProxyInstance() arg2-->指派方法調(diào)用的調(diào)用處理程序(此處就是去調(diào)用this對(duì)象的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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

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
* 說(shuō)明:屬性文件操作工具類
12
*/
13
14
public class PropertiesUtil {
15
private static Properties properties = new Properties();
16
private static FileInputStream fileInputStream;
17
18
/**
19
* 從屬性文件中根據(jù)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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

4:測(cè)試客戶端
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
* 說(shuō)明:動(dòng)態(tài)代理連接池測(cè)試客戶端
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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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

2

3

4

5

6

7

8

9

10

源碼下載 -- (ConnectionPool.rar)
杰森
郵箱:json.shen(at)gmail.com
網(wǎng)站:www.shenjia.org