📄 connectionpool-servlet.htm
字号:
<html><!-- #BeginTemplate "/Templates/more.dwt" -->
<head>
<!-- #BeginEditable "doctitle" -->
<title>csdn_用连接池提高Servlet访问数据库的效率</title>
<!-- #EndEditable -->
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<STYLE type=text/css>
A:link {
COLOR: #000000; FONT-FAMILY:verdana,宋体,新宋体; TEXT-DECORATION: none
}
A:visited {
COLOR: #333399; FONT-FAMILY:verdana,宋体,新宋体; TEXT-DECORATION: none
}
A:active {
COLOR: #ff0000; FONT-FAMILY:verdana,宋体,新宋体; TEXT-DECORATION: none
}
A:hover {
COLOR: black; TEXT-DECORATION: underline
}
BODY {
COLOR: #000000; FONT-SIZE:9pt; LETTER-SPACING: normal; LINE-HEIGHT: 150%; WORD-SPACING: 2em
}
TH {
FONT-SIZE: 9pt
}
TD {
FONT-SIZE: 9pt
}
TD.page {
COLOR: #000000; FONT-SIZE:9pt; LETTER-SPACING: normal; LINE-HEIGHT: 150%; WORD-SPACING: 2em
}
TD.title {
COLOR: #000000; FONT-FAMILY:verdana,宋体,新宋体
}
TD.detail {
COLOR: #9966ff; FONT-FAMILY:verdana,宋体,新宋体
}
</STYLE>
</head>
<body bgcolor="#FFFFFF" text="#000000" >
<div align="center"></div>
<table width="700" border="0" align="center">
<tr>
<table width="700" border="1" cellpadding="1" cellspacing="0" bordercolorlight="#9898ba" bordercolordark="#000000">
</table>
<br>
<table width="700" border="0">
<tr>
<td width="20"> </td>
<td colspan="2">
<div align="center">
<h3><b><!-- #BeginEditable "5" -->用连接池提高Servlet访问数据库的效率<!-- #EndEditable --></b></h3>
</div>
</td>
<td width="20"> </td>
</tr>
<tr>
<td width="20"> </td>
<td colspan="2"><!-- #BeginEditable "6" --><br>
作者:好兵
<p>Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本。Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据。本文介绍一种充分发挥该特色的实用技术,即数据库连接池。</p>
<p><br>
一、实现连接池的意义</p>
<p>动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证、安全上下文配置这类任务,因而往往成为最为耗时的操作。当然,实际的连接时间开销千变万化,但1到2秒延迟并非不常见。如果某个基于数据库的Web应用只需建立一次初始连接,不同页面请求能够共享同一连接,就能获得显著的性能改善。<br>
Servlet是一个Java类。Servlet引擎(它可能是Web服务软件的一部分,也可能是一个独立的附加模块)在系统启动或Servlet第一次被请求时将该类装入Java虚拟机并创建它的一个实例。不同用户请求由同一Servlet实例的多个独立线程处理。那些要求在不同请求之间持续有效的数据既可以用Servlet的实例变量来保存,也可以保存在独立的辅助对象中。<br>
用JDBC访问数据库首先要创建与数据库之间的连接,获得一个连接对象(Connection),由连接对象提供执行SQL语句的方法。本文介绍的数据库连接池包括一个管理类DBConnectionManager,负责提供与多个连接池对象(DBConnectionPool类)之间的接口。每一个连接池对象管理一组JDBC连接对象,每一个连接对象可以被任意数量的Servlet共享。<br>
类DBConnectionPool提供以下功能:</p>
<p>1) 从连接池获取(或创建)可用连接。<br>
2) 把连接返回给连接池。<br>
3) 在系统关闭时释放所有资源,关闭所有连接。</p>
<p>此外, DBConnectionPool类还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不超过某个预定值。
<br>
管理类DBConnectionManager用于管理多个连接池对象,它提供以下功能:</p>
<p>1) 装载和注册JDBC驱动程序。<br>
2) 根据在属性文件中定义的属性创建连接池对象。<br>
3) 实现连接池名字与其实例之间的映射。<br>
4) 跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池。</p>
<p>本文余下部分将详细说明这两个类,最后给出一个示例演示Servlet使用连接池的一般过程。</p>
<p><br>
二、具体实现</p>
<p>DBConnectionManager.java程序清单如下:</p>
<p>001 import java.io.*;<br>
002 import java.sql.*;<br>
003 import java.util.*;<br>
004 import java.util.Date;<br>
005<br>
006 /**<br>
007 * 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接<br>
008 * 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.<br>
009 */<br>
010 public class DBConnectionManager {<br>
011 static private DBConnectionManager instance; // 唯一实例<br>
012 static private int clients;<br>
013<br>
014 private Vector drivers = new Vector();<br>
015 private PrintWriter log;<br>
016 private Hashtable pools = new Hashtable();<br>
017<br>
018 /**<br>
019 * 返回唯一实例.如果是第一次调用此方法,则创建实例<br>
020 *<br>
021 * @return DBConnectionManager 唯一实例<br>
022 */<br>
023 static synchronized public DBConnectionManager getInstance()
{<br>
024 if (instance == null) {<br>
025 instance = new DBConnectionManager();<br>
026 }<br>
027 clients++;<br>
028 return instance;<br>
029 }<br>
030<br>
031 /**<br>
032 * 建构函数私有以防止其它对象创建本类实例<br>
033 */<br>
034 private DBConnectionManager() {<br>
035 init();<br>
036 }<br>
037<br>
038 /**<br>
039 * 将连接对象返回给由名字指定的连接池<br>
040 *<br>
041 * @param name 在属性文件中定义的连接池名字<br>
042 * @param con 连接对象<br>
043 */<br>
044 public void freeConnection(String name, Connection con) {<br>
045 DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br>
046 if (pool != null) {<br>
047 pool.freeConnection(con);<br>
048 }<br>
049 }<br>
050<br>
051 /**<br>
052 * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数<br>
053 * 限制,则创建并返回新连接<br>
054 *<br>
055 * @param name 在属性文件中定义的连接池名字<br>
056 * @return Connection 可用连接或null<br>
057 */<br>
058 public Connection getConnection(String name) {<br>
059 DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br>
060 if (pool != null) {<br>
061 return pool.getConnection();<br>
062 }<br>
063 return null;<br>
064 }<br>
065<br>
066 /**<br>
067 * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,<br>
068 * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.<br>
069 *<br>
070 * @param name 连接池名字<br>
071 * @param time 以毫秒计的等待时间<br>
072 * @return Connection 可用连接或null<br>
073 */<br>
074 public Connection getConnection(String name, long time) {<br>
075 DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br>
076 if (pool != null) {<br>
077 return pool.getConnection(time);<br>
078 }<br>
079 return null;<br>
080 }<br>
081<br>
082 /**<br>
083 * 关闭所有连接,撤销驱动程序的注册<br>
084 */<br>
085 public synchronized void release() {<br>
086 // 等待直到最后一个客户程序调用<br>
087 if (--clients != 0) {<br>
088 return;<br>
089 }<br>
090<br>
091 Enumeration allPools = pools.elements();<br>
092 while (allPools.hasMoreElements()) {<br>
093 DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();<br>
094 pool.release();<br>
095 }<br>
096 Enumeration allDrivers = drivers.elements();<br>
097 while (allDrivers.hasMoreElements()) {<br>
098 Driver driver = (Driver) allDrivers.nextElement();<br>
099 try {<br>
100 DriverManager.deregisterDriver(driver);<br>
101 log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");<br>
102 }<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -