??1
package
?ConnectionPool;?
??2
/**?*/
/**
?
??3
此內部類定義了一個連接池。它能夠根據要求創建新連接,直到預定的最大連接數為止。在返回連接給客戶程序之前,它能夠?
??4
驗證連接的有效性。此類提供以下功能:?
??5
1.從連接池獲取(或創建)可用連接?
??6
2.把連接返回給連接池?
??7
3.在系統關閉時釋放所有資源,關閉所有連接?
??8
4.處理無效連接(原來登記為可用的連接,由于某種原因不再可用,如超時,通訊問題)?
??9
5.限制連接池中的連接總數不超過某個預定值?
?10
*/
?
?11
import
?java.io.
*
;?
?12
import
?java.sql.
*
;?
?13
import
?java.util.
*
;?
?14
import
?java.util.Date;?
?15
?16
class
?DBConnectionPool?
?17
{?
?18
????
private
?
int
?checkedOut;?
?19
????
private
?PrintWriter?logPrint;?
?20
????
private
?Vector?freeConnections?
=
?
new
?Vector();?
?21
????
private
?
int
?maxConn;?
?22
????
private
?String?name;?
?23
????
private
?String?password;?
?24
????
private
?String?URL;?
?25
????
private
?String?user;?
?26
????
?27
????
/**?*/
/**
?
?28
????創建新的連接池?
?29
????*
@param
?name?連接池名字?
?30
????*
@param
?URL?數據庫的JDBC?URL?
?31
????*
@param
?user?數據庫帳號,或null?
?32
????*
@param
?password?密碼,或null?
?33
????*
@param
?maxConn?此連接池允許建立的最大連接數?
?34
????
*/
?
?35
????
public
?DBConnectionPool(String?name,?String?URL,?String?user,?String?password,?
int
?maxConn)?
{?
?36
????????
this
.name?
=
?name;?
?37
????????
this
.URL?
=
?URL;?
?38
????????
this
.user?
=
?user;?
?39
????????
this
.password?
=
?password;?
?40
????????
this
.maxConn?
=
?maxConn;?
?41
????????InputStream?is?
=
?getClass().getResourceAsStream(
"
/db.properties
"
);?
?42
????????Properties?dbProps?
=
?
new
?Properties();?
?43
????????
try
?
{?
?44
????????????dbProps.load(is);?
?45
????????}
?
?46
????????
catch
(Exception?e)?
{?
?47
????????????System.err.println(
"
不能讀取屬性文件.
"
?
+
?
"
請確保db.properties在CLASSPATH指定的路徑中
"
);?
?48
????????????
return
;?
?49
????????}
?
?50
????????String?logFile?
=
?dbProps.getProperty(
"
Poollogfile
"
,?
"
DBConnectionPool.log
"
);?
?51
????????
try
?
{?
?52
????????????logPrint?
=
?
new
?PrintWriter(
new
?FileWriter(logFile,?
true
),?
true
);?
?53
????????}
?
?54
????????
catch
(IOException?e)?
{?
?55
????????????System.err.println(
"
無法打開日志文件:
"
?
+
?logFile);?
?56
????????????logPrint?
=
?
new
?PrintWriter(System.err);?
?57
????????}
?
?58
????}
?
?59
????
?60
????
?61
????
/**?*/
/**
?
?62
????將不再使用的連接返回給連接池?
?63
????*
@param
?con?客戶程序釋放的連接?
?64
????
*/
?
?65
????
public
?
synchronized
?
void
?freeConnection(Connection?con)?
{?
?66
????????freeConnections.addElement(con);?
?67
????????checkedOut
--
;?
?68
????????notifyAll();?
?69
????}
?
?70
????
?71
????
?72
????
/**?*/
/**
?
?73
????從連接池獲得一個可用連接,如沒有空閑的連接且當前連接數小于最大連接數,則創建新連接,?
?74
????如原來登記為可用的連接不再有效,則從向量刪除之,然后遞歸調用自己以嘗試新的可用連接?
?75
????
*/
?
?76
????
public
?
synchronized
?Connection?getConnection()?
{?
?77
????????Connection?con?
=
?
null
;?
?78
????????
if
(freeConnections.size()?
>
?
0
)?
{??
//
?獲取向量中第一個可用連接?
?79
????????????con?
=
?(Connection)freeConnections.firstElement();?
?80
????????????freeConnections.removeElementAt(
0
);?
?81
????????????
try
?
{?
?82
????????????????
if
(con.isClosed())?
{?
?83
????????????????????log(
"
從連接池
"
?
+
?name?
+
?
"
刪除一個無效連接
"
);?
?84
????????????????????con?
=
?getConnection();?
?85
????????????????}
?
?86
????????????}
?
?87
????????????
catch
(SQLException?e)?
{?
?88
????????????????log(
"
從連接池
"
?
+
?name?
+
?
"
刪除一個無效連接
"
);?
?89
????????????????con?
=
?getConnection();?
?90
????????????}
?
?91
????????}
?
?92
????????
else
?
if
(maxConn?
==
?
0
?
||
?checkedOut?
<
?maxConn)?
{?
?93
????????????con?
=
?newConnection();?
?94
????????}
?
?95
????????
if
(con?
!=
?
null
)?
{?
?96
????????????checkedOut
++
;?
?97
????????}
?
?98
????????
return
?con;?
?99
????}
?
100
????
101
????
102
????
/**?*/
/**
?
103
????從連接池獲取可用連接,可以指定客戶程序能夠等待的最長時間?
104
????*
@param
?timeout?以毫秒計的等待時間限制?
105
????
*/
?
106
????
public
?
synchronized
?Connection?getConnection(
long
?timeout)?
{?
107
????????
long
?startTime?
=
?
new
?Date().getTime();?
108
????????Connection?con;?
109
????????
while
((con?
=
?getConnection())?
==
?
null
)?
{?
110
????????????
try
?
{?
111
????????????????wait(timeout);?
112
????????????}
?
113
????????????
catch
(InterruptedException?e)
{}
?
114
????????????
115
????????????
if
((
new
?Date().getTime()?
-
?startTime)?
>=
?timeout)?
{?
116
????????????????
return
?
null
;?
117
????????????}
?
118
????????}
?
119
????????
return
?con;?
120
????}
?
121
????
122
????
123
????
/**?*/
/**
?
124
????關閉所有連接?
125
????
*/
?
126
????
public
?
synchronized
?
void
?release()?
{?
127
????????Enumeration?allConnections?
=
?freeConnections.elements();?
128
????????
while
(allConnections.hasMoreElements())?
{?
129
????????????Connection?con?
=
?(Connection)allConnections.nextElement();?
130
????????????
try
?
{?
131
????????????????con.close();?
132
????????????????log(
"
關閉連接池
"
?
+
?name?
+
?
"
中的一個連接
"
);?
133
????????????}
?
134
????????????
catch
(SQLException?e)?
{?
135
????????????????log(e,?
"
無法關閉連接池
"
?
+
?name?
+
?
"
中的連接
"
);?
136
????????????}
?
137
????????}
?
138
????????freeConnections.removeAllElements();?
139
????}
?
140
????
141
????
142
????
/**?*/
/**
?
143
????創建新的連接?
144
????
*/
?
145
????
private
?Connection?newConnection()?
{?
146
????????Connection?con?
=
?
null
;?
147
????????
try
?
{?
148
????????????
if
(user?
==
?
null
)?
{?
149
????????????????con?
=
?DriverManager.getConnection(URL);?
150
????????????}
?
151
????????????
else
?
{?
152
????????????????con?
=
?DriverManager.getConnection(URL,?user,?password);?
153
????????????}
?
154
????????????log(
"
連接池
"
?
+
?name?
+
?
"
創建一個新的連接
"
);?
155
????????}
?
156
????????
catch
(SQLException?e)?
{?
157
????????????log(e,?
"
無法創建下列URL的連接
"
?
+
?URL);?
158
????????????
return
?
null
;?
159
????????}
?
160
????????
return
?con;?
161
????}
?
162
????
163
????
164
????
/**?*/
/**
?
165
????將文本信息寫入日志文件?
166
????缺省為packaged?
167
????
*/
?
168
????
void
?log(String?msg)?
{?
169
????????logPrint.println(
new
?Date()?
+
?
"
:?
"
?
+
?msg);?
170
????}
?
171
????
172
????
173
????
/**?*/
/**
?
174
????將文本信息與異常寫入日志文件?
175
????
*/
?
176
????
void
?log(Throwable?e,?String?msg)?
{?
177
????????logPrint.println(
new
?Date()?
+
?
"
:?
"
?
+
?msg);?
178
????????e.printStackTrace(logPrint);?
179
????}
?
180
}
?

??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

108

109



110



111

112

113



114

115



116

117

118

119

120

121

122

123


124

125

126



127

128



129

130



131

132

133

134



135

136

137

138

139

140

141

142


143

144

145



146

147



148



149

150

151



152

153

154

155

156



157

158

159

160

161

162

163

164


165

166

167

168



169

170

171

172

173


174

175

176



177

178

179

180

??1
package
?ConnectionPool;?
??2
??3
/**/
/*
此類用于管理多個連接池對象,它支持對一個或多個由屬性文件定義的數據庫連接池的訪問,客戶程序可以調用getInstance()方法訪問本類的唯一實例。它提供以下功能:?
??4
1.裝載和注冊JDBC驅動程序?
??5
2.根據在屬性文件中定義的屬性創建連接池對象?
??6
3.實現連接池名字與其實例之間的映射?
??7
4.跟蹤客戶程序對連接池的引用,保證在最后一個客戶程序結束時安全地關閉所有連接池?
??8
*/
?
??9
?10
import
?java.io.
*
;?
?11
import
?java.sql.
*
;?
?12
import
?java.util.
*
;?
?13
//
import?com.supersoftintl.intranet.common.DBConnectionPool;?
?14
//
import?java.util.Date;?
?15
/**?*/
/**
?
?16
*?管理類DBConnectionManager支持對一個或多個由屬性文件定義的數據庫連接?
?17
*?池的訪問.客戶程序可以調用getInstance()方法訪問本類的唯一實例.?
?18
*/
?
?19
public
?
class
?DBConnectionManager?
{?
?20
????
static
?
private
?DBConnectionManager?instance;
/**/
/*
唯一實例
*/
?
?21
????
static
?
private
?
int
?clients;
?22
?????
/**/
/*
該計數代表引用DBConnectionManager唯一實例的客戶程序總數,?
?23
????它將被用于控制連接池的關閉操作?
*/
?
?24
????
?25
????
static
?
private
?String?DEFAULTCONNECTIONPOOL?
=
?
"
ConnectionPool
"
;?
?26
????
private
?Vector?drivers?
=
?
new
?Vector();?
?27
????
private
?PrintWriter?logPrint;?
?28
????
private
?Hashtable?pools?
=
?
new
?Hashtable();?
?29
????
?30
????
/**?*/
/**
?
?31
????返回唯一實例。如果是第一次調用此方法,則創建實例?
?32
????
*/
?
?33
????
static
?
synchronized
?
public
?DBConnectionManager?getInstance()?
{?
?34
????????
if
(instance?
==
?
null
)?
{?
?35
????????????instance?
=
?
new
?DBConnectionManager();?
?36
????????}
?
?37
????????clients
++
;?
?38
????????
return
?instance;?
?39
????}
?
?40
????
?41
????
?42
????
/**?*/
/**
?
?43
????建構函數私有以防止其它對象創建本類實例?
?44
????
*/
?
?45
????
public
?DBConnectionManager()?
{?
?46
????????init();?
?47
????}
?48
????
?49
????
?50
????
/**?*/
/**
?Added?by?leo?on?2001-5-23?
?51
????使用默認的連接池名,創建并返回新連接?
?52
????*?
?53
????*?
@return
?Connection?可用連接或null?
?54
????
*/
?
?55
????
public
?Connection?getConnection()?
{?
?56
????????
return
?getConnection(DEFAULTCONNECTIONPOOL);?
?57
????}
?
?58
????
?59
????
?60
????
/**?*/
/**
?
?61
????獲得一個可用的(空閑的)連接.如果沒有可用連接,且已有連接數小于最大連接數?
?62
????限制,則創建并返回新連接?
?63
????*?
?64
????*?
@param
?name?在屬性文件中定義的連接池名字?
?65
????*?
@return
?Connection?可用連接或null?
?66
????
*/
?
?67
????
public
?Connection?getConnection(String?name)?
{?
?68
????????DBConnectionPool?pool?
=
?(DBConnectionPool)pools.get(name);?
?69
????????
if
(pool?
!=
?
null
)?
{?
?70
????????????
return
?pool.getConnection();?
?71
????????}
?
?72
????????
return
?
null
;?
?73
????}
?
?74
????
?75
????
?76
????
/**?*/
/**
?
?77
????獲得一個可用連接.若沒有可用連接,且已有連接數小于最大連接數限制,?
?78
????則創建并返回新連接.否則,在指定的時間內等待其它線程釋放連接.?
?79
????*?
?80
????*?
@param
?name?連接池名字?
?81
????*?
@param
?time?以毫秒計的等待時間?
?82
????*?
@return
?Connection?可用連接或null?
?83
????
*/
?
?84
????
public
?Connection?getConnection(String?name,?
long
?time)?
{?
?85
????????DBConnectionPool?pool?
=
?(DBConnectionPool)pools.get(name);?
?86
????????
if
(pool?
!=
?
null
)?
{?
?87
????????????
return
?pool.getConnection(time);?
?88
????????}
?
?89
????????
return
?
null
;?
?90
????}
?
?91
????
?92
????
?93
????
/**?*/
/**
?Added?by?leo?on?2001-5-23?
?94
????將連接對象返回給默認的連接池?
?95
????*?
?96
????*?
@param
?con?連接對象?
?97
????
*/
?
?98
????
public
?
void
?freeConnection(Connection?con)?
{?
?99
????????String?name?
=
?DEFAULTCONNECTIONPOOL;?
100
????????freeConnection(name,con);?
101
????}
?
102
????
103
????
104
????
/**?*/
/**
?
105
????將連接對象返回給由名字指定的連接池?
106
????*?
107
????*?
@param
?name?在屬性文件中定義的連接池名字?
108
????*?
@param
?con?連接對象?
109
????
*/
?
110
????
public
?
void
?freeConnection(String?name,?Connection?con)?
{?
111
????????DBConnectionPool?pool?
=
?(DBConnectionPool)pools.get(name);?
112
????????
if
(pool?
!=
?
null
)?
{?
113
????????????pool.freeConnection(con);?
114
????????}
?
115
????}
?
116
????
117
????
118
????
/**?*/
/**
?
119
????關閉所有連接,撤銷驅動程序的注冊?
120
????
*/
?
121
????
public
?
synchronized
?
void
?release()?
{?
//
?等待直到最后一個客戶程序調用?
122
????????
if
(
--
clients?
!=
?
0
)?
{?
123
????????????
return
;?
124
????????}
?
125
????????Enumeration?allPools?
=
?pools.elements();?
126
????????
while
(allPools.hasMoreElements())?
{?
127
????????????DBConnectionPool?pool?
=
?(DBConnectionPool)allPools.nextElement();?
128
????????????pool.release();?
129
????????}
?
130
????????Enumeration?allDrivers?
=
?drivers.elements();?
131
????????
while
(allDrivers.hasMoreElements())?
{?
132
????????????Driver?driver?
=
?(Driver)allDrivers.nextElement();?
133
????????????
try
?
{?
134
????????????????DriverManager.deregisterDriver(driver);?
135
????????????????log(
"
撤消JDBC驅動程序
"
?
+
?driver.getClass().getName()?
+
?
"
的注冊
"
);?
136
????????????}
?
137
????????????
catch
(SQLException?e)?
{?
138
????????????????log(e,?
"
無法撤消下列JDBC驅動程序的注冊
"
?
+
?driver.getClass().getName());?
139
????????????}
?
140
????????}
?
141
????}
?
142
????
143
????
144
????
/**?*/
/**
?
145
????根據指定屬性創建連接池實例.?
146
????*?
147
????*?
@param
?props?連接池屬性?
148
????
*/
?
149
????
private
?
void
?createPools(Properties?props)?
{?
150
????????Enumeration?propNames?
=
?props.propertyNames();?
151
????????
while
(propNames.hasMoreElements())?
{?
152
????????????String?name?
=
?(String)propNames.nextElement();?
153
????????????
if
(name.endsWith(
"
.url
"
))?
{?
154
????????????????String?poolName?
=
?name.substring(
0
,?name.lastIndexOf(
"
.
"
));?
155
????????????????String?url?
=
?props.getProperty(poolName?
+
?
"
.url
"
);?
156
????????????????
if
(url?
==
?
null
)?
{?
157
????????????????????log(
"
沒有為連接池
"
?
+
?poolName?
+
?
"
指定URL
"
);?
158
????????????????????
continue
;?
159
????????????????}
?
160
????????????????String?user?
=
?props.getProperty(poolName?
+
?
"
.user
"
);?
161
????????????????String?password?
=
?props.getProperty(poolName?
+
?
"
.password
"
);?
162
????????????????String?maxconn?
=
?props.getProperty(poolName?
+
?
"
.maxconn
"
,?
"
0
"
);?
163
????????????????
int
?max;?
164
????????????????
try
?
{?
165
????????????????????max?
=
?Integer.valueOf(maxconn).intvalue();?
166
????????????????}
?
167
????????????????
catch
(NumberformatException?e)?
{?
168
????????????????????log(
"
錯誤的最大連接數限制:
"
?
+
?maxconn?
+
?
"
.連接池:
"
?
+
?poolName);?
169
????????????????????log(
"
自動改變設置為0--即無限制
"
);?
170
????????????????????max?
=
?
0
;?
171
????????????????}
?
172
????????????????DBConnectionPool?pool?
=
?
new
?DBConnectionPool(poolName,?url,?user,?password,?max);?
173
????????????????pools.put(poolName,?pool);?
174
????????????????log(
"
成功創建連接池
"
?
+
?poolName);?
175
????????????}
?
176
????????}
?
177
????}
?
178
????
179
????
180
????
/**?*/
/**
?
181
????讀取屬性完成初始化?
182
????
*/
?
183
????
private
?
void
?init()?
{?
184
????????InputStream?is?
=
?getClass().getResourceAsStream(
"
/db.properties
"
);?
185
????????Properties?dbProps?
=
?
new
?Properties();?
186
????????
try
?
{?
187
????????????dbProps.load(is);?
188
????????}
?
189
????????
catch
(Exception?e)?
{?
190
????????????System.err.println(
"
不能讀取屬性文件.
"
?
+
?
"
請確保db.properties在CLASSPATH指定的路徑中
"
);?
191
????????????
return
;?
192
????????}
?
193
????????String?logFile?
=
?dbProps.getProperty(
"
Managerlogfile
"
,?
"
DBConnectionManager.log
"
);?
194
????????
try
?
{?
195
????????????logPrint?
=
?
new
?PrintWriter(
new
?FileWriter(logFile,?
true
),?
true
);?
196
????????}
?
197
????????
catch
(IOException?e)?
{?
198
????????????System.err.println(
"
無法打開日志文件:
"
?
+
?logFile);?
199
????????????logPrint?
=
?
new
?PrintWriter(System.err);?
200
????????}
?
201
????????loadDrivers(dbProps);?
202
????????createPools(dbProps);?
203
????}
?
204
????
205
????
206
????
/**?*/
/**
?
207
????裝載和注冊所有JDBC驅動程序?
208
????*?
209
????*?
@param
?props?屬性?
210
????
*/
?
211
????
private
?
void
?loadDrivers(Properties?props)?
{?
212
????????String?driverClasses?
=
?props.getProperty(
"
drivers
"
);?
213
????????StringTokenizer?st?
=
?
new
?StringTokenizer(driverClasses);?
214
????????
while
(st.hasMoreElements())?
{?
215
????????????String?driverClassName?
=
?st.nextToken().trim();?
216
????????????
try
?
{?
217
????????????????Driver?driver?
=
?(Driver)Class.forName(driverClassName).newInstance();?
218
????????????????DriverManager.registerDriver(driver);?
219
????????????????drivers.addElement(driver);?
220
????????????????log(
"
成功JDBC注冊驅動程序
"
?
+
?driverClassName);?
221
????????????}
?
222
????????????
catch
(Exception?e)?
{?
223
????????????????log(
"
無法注冊JDBC驅動程序;
"
?
+
?driverClassName?
+
?
"
,錯誤:
"
?
+
?e);?
224
????????????}
?
225
????????}
?
226
????}
?
227
????
228
????
229
????
/**?*/
/**
?
230
????將文本信息寫入日志文件?
231
????缺省為packaged?
232
????
*/
?
233
????
void
?log(String?msg)?
{?
234
????????logPrint.println(
new
?java.util.Date()?
+
?
"
:?
"
?
+
?msg);?
235
????}
?
236
????
237
????
238
????
/**?*/
/**
?
239
????將文本信息與異常寫入日志文件?
240
????
*/
?
241
????
void
?log(Throwable?e,?String?msg)?
{?
242
????????logPrint.println(
new
?java.util.Date()?
+
?
"
:?
"
?
+
?msg);?
243
????????e.printStackTrace(logPrint);?
244
????}
?
245
}
?

??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

108

109

110



111

112



113

114

115

116

117

118


119

120

121



122



123

124

125

126



127

128

129

130

131



132

133



134

135

136

137



138

139

140

141

142

143

144


145

146

147

148

149



150

151



152

153



154

155

156



157

158

159

160

161

162

163

164



165

166

167



168

169

170

171

172

173

174

175

176

177

178

179

180


181

182

183



184

185

186



187

188

189



190

191

192

193

194



195

196

197



198

199

200

201

202

203

204

205

206


207

208

209

210

211



212

213

214



215

216



217

218

219

220

221

222



223

224

225

226

227

228

229


230

231

232

233



234

235

236

237

238


239

240

241



242

243

244

245
