📄 connectionpool-servlet.htm
字号:
103 catch (SQLException e) {<br>
104 log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());<br>
105 }<br>
106 }<br>
107 }<br>
108<br>
109 /**<br>
110 * 根据指定属性创建连接池实例.<br>
111 *<br>
112 * @param props 连接池属性<br>
113 */<br>
114 private void createPools(Properties props) {<br>
115 Enumeration propNames = props.propertyNames();<br>
116 while (propNames.hasMoreElements()) {<br>
117 String name = (String) propNames.nextElement();<br>
118 if (name.endsWith(".url")) {<br>
119 String poolName = name.substring(0, name.lastIndexOf("."));<br>
120 String url = props.getProperty(poolName + ".url");<br>
121 if (url == null) {<br>
122 log("没有为连接池" + poolName + "指定URL");<br>
123 continue;<br>
124 }<br>
125 String user = props.getProperty(poolName + ".user");<br>
126 String password = props.getProperty(poolName + ".password");<br>
127 String maxconn = props.getProperty(poolName + ".maxconn",
"0");<br>
128 int max;<br>
129 try {<br>
130 max = Integer.valueOf(maxconn).intValue();<br>
131 }<br>
132 catch (NumberFormatException e) {<br>
133 log("错误的最大连接数限制: " + maxconn + " .连接池: "
+ poolName);<br>
134 max = 0;<br>
135 }<br>
136 DBConnectionPool pool =<br>
137 new DBConnectionPool(poolName, url, user, password, max);<br>
138 pools.put(poolName, pool);<br>
139 log("成功创建连接池" + poolName);<br>
140 }<br>
141 }<br>
142 }<br>
143<br>
144 /**<br>
145 * 读取属性完成初始化<br>
146 */<br>
147 private void init() {<br>
148 InputStream is = getClass().getResourceAsStream("/db.properties");<br>
149 Properties dbProps = new Properties();<br>
150 try {<br>
151 dbProps.load(is);<br>
152 }<br>
153 catch (Exception e) {<br>
154 System.err.println("不能读取属性文件. " +<br>
155 "请确保db.properties在CLASSPATH指定的路径中");<br>
156 return;<br>
157 }<br>
158 String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");<br>
159 try {<br>
160 log = new PrintWriter(new FileWriter(logFile, true), true);<br>
161 }<br>
162 catch (IOException e) {<br>
163 System.err.println("无法打开日志文件: " + logFile);<br>
164 log = new PrintWriter(System.err);<br>
165 }<br>
166 loadDrivers(dbProps);<br>
167 createPools(dbProps);<br>
168 }<br>
169<br>
170 /**<br>
171 * 装载和注册所有JDBC驱动程序<br>
172 *<br>
173 * @param props 属性<br>
174 */<br>
175 private void loadDrivers(Properties props) {<br>
176 String driverClasses = props.getProperty("drivers");<br>
177 StringTokenizer st = new StringTokenizer(driverClasses);<br>
178 while (st.hasMoreElements()) {<br>
179 String driverClassName = st.nextToken().trim();<br>
180 try {<br>
181 Driver driver = (Driver)<br>
182 Class.forName(driverClassName).newInstance();<br>
183 DriverManager.registerDriver(driver);<br>
184 drivers.addElement(driver);<br>
185 log("成功注册JDBC驱动程序" + driverClassName);<br>
186 }<br>
187 catch (Exception e) {<br>
188 log("无法注册JDBC驱动程序: " +<br>
189 driverClassName + ", 错误: " + e);<br>
190 }<br>
191 }<br>
192 }<br>
193<br>
194 /**<br>
195 * 将文本信息写入日志文件<br>
196 */<br>
197 private void log(String msg) {<br>
198 log.println(new Date() + ": " + msg);<br>
199 }<br>
200<br>
201 /**<br>
202 * 将文本信息与异常写入日志文件<br>
203 */<br>
204 private void log(Throwable e, String msg) {<br>
205 log.println(new Date() + ": " + msg);<br>
206 e.printStackTrace(log);<br>
207 }<br>
208<br>
209 /**<br>
210 * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最<br>
211 * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.<br>
212 */<br>
213 class DBConnectionPool {<br>
214 private int checkedOut;<br>
215 private Vector freeConnections = new Vector();<br>
216 private int maxConn;<br>
217 private String name;<br>
218 private String password;<br>
219 private String URL;<br>
220 private String user;<br>
221<br>
222 /**<br>
223 * 创建新的连接池<br>
224 *<br>
225 * @param name 连接池名字<br>
226 * @param URL 数据库的JDBC URL<br>
227 * @param user 数据库帐号,或 null<br>
228 * @param password 密码,或 null<br>
229 * @param maxConn 此连接池允许建立的最大连接数<br>
230 */<br>
231 public DBConnectionPool(String name, String URL, String user,
String password,<br>
232 int maxConn) {<br>
233 this.name = name;<br>
234 this.URL = URL;<br>
235 this.user = user;<br>
236 this.password = password;<br>
237 this.maxConn = maxConn;<br>
238 }<br>
239<br>
240 /**<br>
241 * 将不再使用的连接返回给连接池<br>
242 *<br>
243 * @param con 客户程序释放的连接<br>
244 */<br>
245 public synchronized void freeConnection(Connection con) {<br>
246 // 将指定连接加入到向量末尾<br>
247 freeConnections.addElement(con);<br>
248 checkedOut--;<br>
249 notifyAll();<br>
250 }<br>
251<br>
252 /**<br>
253 * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接<br>
254 * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,<br>
255 * 然后递归调用自己以尝试新的可用连接.<br>
256 */<br>
257 public synchronized Connection getConnection() {<br>
258 Connection con = null;<br>
259 if (freeConnections.size() > 0) {<br>
260 // 获取向量中第一个可用连接<br>
261 con = (Connection) freeConnections.firstElement();<br>
262 freeConnections.removeElementAt(0);<br>
263 try {<br>
264 if (con.isClosed()) {<br>
265 log("从连接池" + name+"删除一个无效连接");<br>
266 // 递归调用自己,尝试再次获取可用连接<br>
267 con = getConnection();<br>
268 }<br>
269 }<br>
270 catch (SQLException e) {<br>
271 log("从连接池" + name+"删除一个无效连接");<br>
272 // 递归调用自己,尝试再次获取可用连接<br>
273 con = getConnection();<br>
274 }<br>
275 }<br>
276 else if (maxConn == 0 || checkedOut < maxConn) {<br>
277 con = newConnection();<br>
278 }<br>
279 if (con != null) {<br>
280 checkedOut++;<br>
281 }<br>
282 return con;<br>
283 }<br>
284<br>
285 /**<br>
286 * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间<br>
287 * 参见前一个getConnection()方法.<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -