package mc;
import java.util.*;
import java.util.Date;
import java.sql.*;
import java.io.*;
public class DBConnectionManager {
/** 日志文件写入流对象 */
private PrintWriter log;
/** 存放连接池对象Hashtable */
private Hashtable pools;
/** DBConnectionManager 唯一实例 */
static private DBConnectionManager instance;
/** 记录客户机的连接数 */
static private int remotes;
/** 存放数据库连接驱动 */
private Vector drivers;
/**
* 类名: DBConnectionManager<br>
* 函数功能: 私有构造方法<br>
* 返回值: 无<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private DBConnectionManager()
{
init();
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 初始化类属性<br>
* 返回值: 无<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private void init()
{
pools = new Hashtable();
drivers = new Vector();
//建立属性对象
Properties prop = new Properties();
//把属性文件的属性列表读到属性对象
try {
InputStream is = getClass().getResourceAsStream("db.properties");
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
System.out.println("读取属性文件错误!");
}
// 建立日志文件输入流对象
String logFilePath = prop.getProperty("logFile");
try {
log = new PrintWriter(new FileWriter(logFilePath,true),true);
} catch (IOException e) {
e.printStackTrace();
System.out.println("无法打开日志文件:" + logFilePath);
log = new PrintWriter(System.err);
}
// 加载和注册数据库驱动
loadDriver(prop);
// 初始化和创建连接池实例
createPools(prop);
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 返回 DBConnectionManager 唯一实例.如果是第一次调用此方法,则创建实例<br>
* 返回值: DBConnectionManager 对象<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
static synchronized public DBConnectionManager getInstance()
{
if(instance == null){
instance = new DBConnectionManager();
}
remotes++;
return instance;
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 把文本信息写入日志文件<br>
* 返回值: 无<br>
* 参数说明: String message 信息描述字符串<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private void logWriter(String message)
{
log.println("日期: " + new Date() + message);
}
private void logWriter(Throwable e,String errMessage)
{
log.println("日期: " + new Date() + errMessage + "\n错误: ");
e.printStackTrace(log); // 把异常描述写入日志文件
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 获取一个数据库连接<br>
* 返回值: Connection类型<br>
* 参数说明: String poolName 接收连接池名称<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public Connection getConnection(String poolName)
{
// 通过连接池名称返回连接池对象
DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
if(pool == null){
logWriter("试图使用不存在的连接池" + poolName);
return null;
}
// 返回连接给用户.
return pool.getConnection();
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 释放连接,把用完的连接归还给连接池<br>
* 返回值: 无<br>
* 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public void RefeaseConnection(String poolName,Connection conn)
{
DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
if(pool == null){
logWriter("释放连错误!请检查连接池名称.");
return;
}else{
pool.freeConnection(conn);
}
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 释放连接,把用完的连接归还给连接池<br>
* 返回值: 无<br>
* 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public void RefeaseConnection
(String poolName,Connection conn,Statement stn,PreparedStatement ptn,ResultSet result)
{
try {
if (stn != null)
stn.close();
if (ptn != null)
ptn.close();
if (result != null)
result.close();
}catch(Exception ex)
{
ex.printStackTrace(System.out);
System.out.println(ex.getMessage());
}
DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
if(pool == null){
logWriter("释放连错误!请检查连接池名称.");
return;
}else{
pool.freeConnection(conn);
}
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 释放所有的连接,注销驱动<br>
* 返回值: 无<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public synchronized void releas()
{
if(--remotes != 0){
return;
}
Enumeration ePools = pools.elements();
while(ePools.hasMoreElements()){
DBConnectionPool pool = (DBConnectionPool) ePools.nextElement();
//关闭所有的连接对象
pool.release();
}
Enumeration eDrivers = drivers.elements();
while(eDrivers.hasMoreElements()){
Driver driver = (Driver) eDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logWriter("注销" + driver.getClass().getName() + "成功!");
} catch (SQLException e) {
logWriter(e,"无法注销" + driver.getClass().getName() + "驱动!");
e.printStackTrace();
}
}
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 加载和注册数据库驱动程序<br>
* 返回值: 无<br>
* 参数说明: Properties prop变量接收数据库属性列表<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private void loadDriver(Properties prop)
{
// 从prop属性对象中取出驱动字符串
String driverClass = prop.getProperty("drivers");
// 把驱动字符串分解为标记
StringTokenizer st = new StringTokenizer(driverClass);
while(st.hasMoreTokens()){
String driverClassName = st.nextToken().trim();
try {
// 加载数据库驱动
Driver driver = (Driver) Class.forName(driverClassName).newInstance();
// 注册数据库驱动
DriverManager.registerDriver(driver);
drivers.addElement(driver);
// 把注册相关信息写入日志文件
logWriter("成功注册数据库驱动.");
} catch (InstantiationException e) {
logWriter("加载数据库驱动错误:" + e.getMessage());
e.printStackTrace();
} catch (IllegalAccessException e) {
logWriter("加载数据库驱动错误:" + e.getMessage());
e.printStackTrace();
} catch (ClassNotFoundException e) {
logWriter("加载数据库驱动错误:" + e.getMessage());
e.printStackTrace();
} catch (SQLException e) {
logWriter("无法数据库驱动:" + e.getMessage());
e.printStackTrace();
}
}
}
/**
* 类名: DBConnectionManager<br>
* 函数功能: 初始化和建立连接池实例<br>
* 返回值: 无<br>
* 参数说明: Properties prop 变量接收设置连接池属性列表;如 最大连接数,最少连接数等<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private void createPools(Properties prop)
{
/** 返回属性列表中所有键的枚举 */
Enumeration propNames = prop.propertyNames();
while(propNames.hasMoreElements()){
String name = (String) propNames.nextElement();
if(name.endsWith(".url")){
// propName 以后用做连接池名称
String poolName = name.substring(0,name.indexOf("."));
String url = prop.getProperty(poolName + ".url").trim();
if(poolName == null || url == null){
log.print("没有连接池:" + poolName + " 指定的URL");
continue;
}
String user = prop.getProperty(poolName + ".user").trim();
String password = prop.getProperty(poolName + ".password").trim();
String strMaxConn = prop.getProperty(poolName + ".maxConn").trim();
String strMinConn = prop.getProperty(poolName + ".minConn").trim();
int maxConn = 0,minConn = 0;
try{
maxConn = Integer.parseInt(strMaxConn);
minConn = Integer.parseInt(strMinConn);
}catch(NumberFormatException ne){
maxConn = 100;
minConn = 50;
logWriter(ne," 属性文件中的最大连接数错误,请检查书写是否正确!" +
"此错误出现后,系统自动设置最大连接数为100");
}
//取得数据库属性文件中的相关设置后开始建立连接池
DBConnectionPool pool = new DBConnectionPool(poolName,url,user,password,maxConn,minConn);
//把连接池放到 Hashtable
pools.put(poolName, pool);
logWriter("连接池创建成功!");
}
}
}
/**
* 类名: DBConnectionPool类是DBConnectionManager类的内部类<br>
* 内部类功能: 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最大连接数为止.
在返回连接给客户程序之前,它能够验证连接的有效性.<br>
* 返回值: 无<br>
* 参数说明: <br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
class DBConnectionPool
{
/** 记录分出的连接数 */
private int checkOut;
/** 存放连接的 Vector 对象 */
private Vector freeConnection;
/** 数据库帐户 */
private String user;
/** 登陆密码 */
private String password;
/** 连接池名称 */
private String poolName;
/** 数据源URL */
private String url;
/** 最大连接数 */
private int maxConn;
/** 最小连接数 */
private int minConn;
/**
* 类名: DBConnectionPool<br>
* 函数功能: 构造方法<br>
* 返回值: 无<br>
* 参数说明: String poolName 接收连接池名称; String url 数据源URL;
String user 数据库帐户; String password 密码; int maxConn 设置最大的连接数<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public DBConnectionPool(String poolName, String url, String user,
String password, int maxConn,int minConn) {
freeConnection = new Vector();
this.poolName = poolName;
this.url = url;
this.user = user;
this.password = password;
this.maxConn = maxConn;
this.minConn = minConn;
init();
}
/**
* 类名: DBConnectionPool<br>
* 函数功能: 该方法在程序第一次运行时生成最小连接数。<br>
* 返回值: Connection 对象<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
private void init() {
Connection conn = null;
for (int i = 0; i < minConn; i++) {
try {
conn = DriverManager.getConnection(url, user, password);
logWriter("连接池: " + poolName + " 创建了一个新连接");
} catch (SQLException e) {
logWriter(e, "无法建立:" + url + "连接");
e.printStackTrace();
}
freeConnection.addElement(conn);
}
}
/**
* 类名: DBConnectionPool<br>
* 函数功能: 返回连接对象<br>
* 返回值: Connection 对象<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public Connection getConnection(){
Connection conn = null;
if(freeConnection.size() > 0){
//当连接池中有空闲的连接,就从池中取出一条连接
conn = (Connection) freeConnection.firstElement();
//连接取出后,从连接池中删除该连接的记录.
freeConnection.removeElementAt(0);
try {
//判断所取出的连接是否有效
if(conn.isClosed()){
logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");
//递归调用自己,获取可用的连接
conn = getConnection();
}
} catch (SQLException e) {
logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");
e.printStackTrace();
//递归调用自己,获取可用的连接
conn = getConnection();
}
// 当连接池中没有可用的连接,且当前的连接数在设置最大的连接数以下.新建一个连接
}else if(checkOut < maxConn){
conn = newConnection();
// 当连接池中没有可用的连接,且当前连接已经达到最大连接数.
}else{
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//等待500毫秒后,递归调用自己,获取可用的连接
conn = getConnection();
}
// 记录分出去的连接数
checkOut++;
return conn;
}
/**
* 类名: DBConnectionPool<br>
* 函数功能: 返回新建的连接对象<br>
* 返回值: Connection 对象<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
public Connection newConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url,user,password);
logWriter("连接池: " + poolName + " 创建了一个新连接");
} catch (SQLException e) {
logWriter(e,"无法建立:" + url + "连接");
e.printStackTrace();
}
return conn;
}
/**
* 类名: DBConnectionPool<br>
* 函数功能: 释放连接对象<br>
* 返回值: 无<br>
* 参数说明: 无<br>
* 创建人: andy<br>
* 创建时间: 2006年9月1日
* 最后修改: 无<br>
*/
synchronized public void freeConnection(Connection conn)
{
// 把连接对象放回 Vector 里
freeConnection.addElement(conn);
// 连接数减1
checkOut--;
// 唤醒在此对象监视器上等待的所有线程
notifyAll();
}
public synchronized void release()
{
Enumeration allConn = freeConnection.elements();
while(allConn.hasMoreElements()){
Connection conn = (Connection) allConn.nextElement();
try {
conn.close();
logWriter("成功关闭连接!");
} catch (SQLException e) {
logWriter(e,"无法关闭连接池" + poolName + "中连接!");
e.printStackTrace();
}
//清空 Vector 中的所有元素
freeConnection.removeAllElements();
}
}
}
}
相关推荐
Java JDBC 数据库连接池总结 Java 语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁。在 Web 应用开发的早期,主要使用的技术是 CGIASPPHP 等。之后,Sun 公司推出了基于 Java 语言的 ...
Java JDBC 数据库连接池总结 Java JDBC 数据库连接池是 Java 应用程序访问数据库的基本原理之一。Java 语言通过 JDBC 技术访问数据库,JDBC 是一种“开放”的方案,为数据库应用开发人员和数据库前台工具开发人员...
Java 数据库连接池是 Java 应用程序中用于管理数据库连接的重要工具,它极大地提高了应用程序的性能和效率。本文将详细介绍如何在 Java 中实现一个完整的数据库连接池,并探讨其核心概念、工作原理以及如何根据需求...
首先,数据库连接池的基本原理是维护一定数量的数据库连接,当应用需要时,可以从池中获取一个已建立的连接,使用完毕后再归还给池,而不是直接关闭。这样避免了频繁地创建和销毁连接,提高了系统的效率。 1. **...
标题:Java数据库连接池 描述:本篇将详细介绍Java数据库连接池的概念,代码实现以及其在实际项目中的应用。数据库连接池是Java开发中优化数据库访问效率的关键技术,通过复用预创建的数据库连接,避免频繁创建和...
Java数据库连接池是Java开发中一个非常重要的技术,它主要用于管理数据库连接,提高数据库操作的效率和性能。在Java应用程序中,频繁地创建和关闭数据库连接会导致大量的系统资源浪费,而连接池则可以复用已建立的...
数据库连接池是Java开发中非常重要的一个概念,它在处理大量并发访问数据库的应用场景中扮演着关键角色。本文将深入探讨数据库连接池的工作原理、重要性以及如何在Java中实现一个简单的连接池。 首先,数据库连接池...
Java JDBC 数据库连接池技术是Java应用程序访问数据库的关键优化手段,尤其在Web应用程序中,它解决了传统JDBC连接方式存在的效率低下和资源浪费问题。Java JDBC(Java Database Connectivity)是Java语言与各种...
数据库连接池在初始化时会创建一定数量的数据库连接,这些连接在应用程序需要时可以被复用,而不是每次请求时都创建新的连接,从而减少了创建和销毁连接的开销。C3P0作为连接池实现之一,提供了很多配置参数,例如...
虽然现在用APACHE COMMONS DBCP可以非常方便的建立数据库连接池, 但是像这篇文章把数据库连接池的内部原理写的这么透彻,注视这么完整, 真是非常难得,让开发人员可以更深层次的理解数据库连接池。
Java数据库连接池的原理与应用 在Java开发领域,数据库连接池(Database Connection Pool,简称DBCP)是一种提高数据库访问性能、降低资源消耗的重要技术。它通过预先建立一定数量的数据库连接,存储在一个“池”中...
数据库连接池是Java应用程序中非常重要的一个组成部分,它在处理多用户并发访问数据库时能显著提高性能和资源利用率。在给定的标题“自己写的数据库连接池(java)”中,我们可以推测这是一个用户自定义的数据库连接池...
"基于Java的数据库连接池设计与优化" 本文总结了基于Java的数据库连接池设计与优化技术,讨论了传统数据库开发模式的不足,提出了数据库连接池技术,并对其基本模型和设计方案进行了探讨。在静态连接池的设计基础上...
数据库连接池是一种管理数据库连接的机制,它允许程序高效地重复使用已建立的数据库连接,而不是每次需要时都创建新的连接。这显著提高了性能,减少了资源消耗,并降低了数据库服务器的压力。 在Java中,有多种流行...