连接池的设计与实现
2008-12-23
作者:郑平
引 言
通过网络访问数据库时存在访问速度的问题.要综合硬件设施,网络延时,以及出现拥塞的情况下对数据库的访问速度带来的影响.为了提高性能,确保在大量用户访问数据库时,仍能够保持比较快的速度.主要用连接池技术来解决这一矛盾..
实现连接池的意义
动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库" title="连接数据库">连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证、安全上下文配置这类任务,因而往往成为最为耗时的操作。当然,实际的连接时间开销千变万化,但1到2秒延迟并非不常见。如果某个基于数据库的Web应用只需建立一次初始连接,不同页面请求能够共享同一连接,就能获得显著的性能改善。
用JDBC访问数据库首先要创建与数据库之间的连接,获得一个连接对象(Connection),由连接对象提供执行SQL语句的方法。
在企业级应用中,三层结构模型,或者多层结构模型适合当前发展的趋势.主要由EJB技术,
Servlet,Jsp技术实现" title="技术实现">技术实现. 对比之下Jsp实现简单,直观,一般情况下会通过连接池提高访问速度.
实现类.
ConnectionReaper , JDCConnectionPool ,JDCConnectionDriver
,JDCConnection , ConnectionPool
JDCConnectionDriver 类 实现了 java.sql.Driver 接口, 提供加载" title="加载">加载JDBC驱动和创建新的数据库连接的方法. 当应用程序" title="应用程序">应用程序请求一个数据库连接是 一个 JDCConnectionDriver 对象将被创建,静态JDCConnectionPool类对象pool只有JDCConnectionDriver 初始化时且为null时才被创建,以后将被直接使用这个静态对象. JDCConnectionManager 的构造函数将作以下工作:通过DriverManager类完成 JDCConnectionManager对象的注册.加载应用程序通过调用传递给构造函数的指定的驱动.通过特定的database URL, login user ID, login password passed 初始化JDCConnectionPool对象
JDCConnectionPool 类通过getConnection 方法 实现应用程序对数据库的连接.这个方法首先在连接池中寻找一个可用的连接. 如果没有,将创建一个新的连接.如果在连接池中找到一个可用的连接,getConnection方法 将 连接标示为被租用 并且将此连接返回给调用此方法的程序.
JDCConnection.java类代表一个在连接池中的 JDBC连接,是对一个真正的数据库连接的封装. JDCConnection 对象持有 一个状态标值 来标示这个连接是否被占用和已经连接的时间 这个时间戳将被 ConnectionReaper.java 类用来鉴别挂起的接,ConnectionReaper.java 类用来 处理连接池连接数据库时发生的死锁和挂起异常
Connectionreaper类 决定一个连接死亡(不再被占用,或其他异常情况的出现)的条件如下(同时满足以下三种情况).
· 连接被标示为正在被占用.
· 连接超时(连接时间超过了预先设置的 最大" title="最大">最大允许的连接时间.)
· 连接没有通过一个有效性检验. 有效性检验在这个连接上运行一条简单的SQL 查寻语句,检验是否抛出异常. 如果连接没有通过一个有效性检验,它将被关闭.一个新的连接将被初始化加入连接池中.
当应用程序在它的finally 子句中调用JDCConnection.java类的close方法时,连接将被返回给连接池.
public JDCConnectionDriver(String driver, String url, String user, String password)throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException{
if(pool==null){riverManager.registerDriver(this); Class.forName(driver).newInstance();
pool=new JDCConnectionPool(url, user, password); } }
有效性检查方法
public boolean validate() {
try { conn.getMetaData();
}catch (Exception e) {
return false;
}
return true;
}
ConnectionPool类将作为一个Bean,被Jsp脚本加以引用. ConnectionPool间接实现连接池的初始化,通过getConnection方法返回一个连接.
ConnectionPool
public synchronized void returnConnection(JDCConnection conn) { conn.expireLease();}
public class ConnectionPool
{
public synchronized void getInstance(){
try{
new JDCConnectionDriver("com.inet.tds.TdsDriver",
"jdbc:inetdae7:phoenix","sa", "810803"); }catch(Exception e){}
}
public Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:jdc:jdcpool");
}
连接池实现类集的UML图如下
结 束 语
连接池的测试通过pool.jsp测试.其引用与释放情况如下.
connMgr.getInstance();
Connection con = connMgr.getConnection();
if (con == null) {
out.println("不能获取数据库连接.");
return;}
………….
对数据库的各种操作.
…………..
con.close();
连接池的机制深入研究还是比较复杂的.以上只是一个简单实用的连接池的实现,其中用到的驱动是com.inet.tds.TdsDriver.一个免费试用版本.支持的最大连接数为2,说明连接池的效率还是比较好的.一个改进的地方是密码和用户名写在了程序中.通过属性文件可以做到保密性.
参考文献:
1.http://developer.java.sun.com/developer/onlineTraining/Programming/JDCBook/conpool.html
2. http://jakarta.apache.org.