动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   Jsp → 阅读文章

 一个连接池的例子 (一)

作者来源: 
阅读 1717 人次 , 2006-3-29 4:23:00 

//文件:dbconnectiondefaultpool.java的第一部分

//请注意看里面注明的一处需要修改连接参数的地方
package com.qingtuo.db.pool;

import java.sql.*;
import java.util.*;
import java.io.*;
import java.text.*;
import java.util.date;


/**
* default jive connection provider. it uses the excellent connection pool
* available from http://www.javaexchange.com. this connection provider is a
* a good choice unless you can use a container-managed one.
*/
public class dbconnectiondefaultpool extends dbconnectionprovider {

private static final string name = "default connection pool";
private static final string description = "the default connection provider "
+ "that uses the connection pool from javaexchange.com. it works with "
+ "almost any database setup, is customizable, and offers good performance. "
+ "use this connection provider unless you have your own or can use a "
+ "container managed connection pool.";
private static final string author = "coolservlets.com";
private static final int major_version = 1;
private static final int minor_version = 0;
private static final boolean pooled = true;

private connectionpool connectionpool = null;
private properties props;
private properties propdescriptions;

private object initlock = new object();

public dbconnectiondefaultpool() {
//this.manager = manager;
props = new properties();
propdescriptions = new properties();
//initialize all property values
initializeproperties();
//load any existing property values
loadproperties();
}

/**
 * returns a database connection.
 */
public connection getconnection() {
if (connectionpool == null) {
//block until the init has been done
synchronized(initlock) {
//if still null, something has gone wrong
if (connectionpool == null) {
system.err.println("warning: dbconnectiondefaultpool.getconnection() was " +
"called when the internal pool has not been initialized.");
return null;
}
}
}
return new connectionwrapper(connectionpool.getconnection(), connectionpool);
}

/**
 * starts the pool.
 */
protected void start() {
//acquire lock so that no connections can be returned.
synchronized (initlock) {
//get properties
string driver = props.getproperty("driver");
string server = props.getproperty("server");
string username = props.getproperty("username");
string password = props.getproperty("password");
int minconnections = 0, maxconnections = 0;
double connectiontimeout = 0.0;
try {
minconnections = integer.parseint(props.getproperty("minconnections"));
maxconnections = integer.parseint(props.getproperty("maxconnections"));
connectiontimeout = double.parsedouble(props.getproperty("connectiontimeout"));
}
catch (exception e) {
system.err.println("error: could not parse default pool properties. " +
"make sure the values exist and are correct.");
e.printstacktrace();
return;
}
string logpath = props.getproperty("logpath");

try {
connectionpool = new connectionpool(driver, server, username, password,
minconnections, maxconnections, logpath, connectiontimeout);
}
catch (ioexception ioe) {
system.err.println("error starting dbconnectiondefaultpool: " + ioe);
ioe.printstacktrace();
}
}
}

/**
 * restarts the pool to take into account any property changes.
 */
protected void restart() {
//kill off pool.
destroy();
//reload properties.
loadproperties();
//start a new pool.
start();
}

/**
 * destroys the connection pool.
 */
protected void destroy() {
if (connectionpool != null) {
try {
connectionpool.destroy(1);
}
catch (exception e) {
e.printstacktrace();
}
}
//release reference to connectionpool
connectionpool = null;
}

/**
 * returns the value of a property of the connection provider.
 *
 * @param name the name of the property.
 * @returns the value of the property.
 */
public string getproperty(string name) {
return (string)props.get(name);
}

/**
 * returns the description of a property of the connection provider.
 *
 * @param name the name of the property.
 * @return the description of the property.
 */
public string getpropertydescription(string name) {
return (string)propdescriptions.get(name);
}

/**
 * returns an enumeration of the property names for the connection provider.
 */
public enumeration propertynames() {
return props.propertynames();
}

/**
 * sets a property of the connection provider. each provider has a set number
 * of properties that are determined by the author. trying to set a non-
 * existant property will result in an illegalargumentexception.
 *
 * @param name the name of the property to set.
 * @param value the new value for the property.
 *
 */
public void setproperty(string name, string value) {
props.put(name, value);
saveproperties();
}

/**
 * give default values to all the properties and descriptions.
 */
private void initializeproperties() {
props.put("driver","");
props.put("server","");
props.put("username","");
props.put("password","");
props.put("minconnections","");
props.put("maxconnections","");
props.put("logpath","");
props.put("connectiontimeout","");

propdescriptions.put("driver","jdbc driver. e.g. 'oracle.jdbc.driver.oracledriver'");
propdescriptions.put("server","jdbc connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'");
propdescriptions.put("username","database username. e.g. 'scott'");
propdescriptions.put("password","database password. e.g. 'tiger'");
propdescriptions.put("minconnections","minimum # of connections to start with in pool. three is the recommended minimum");
propdescriptions.put("maxconnections","maximum # of connections in dynamic pool. fifteen should give good performance for an average load.");
propdescriptions.put("logpath","absolute path name for log file. e.g. 'c:\\logs\\jivedblog.log'");
propdescriptions.put("connectiontimeout","time in days between connection resets. e.g. '.5'");
}

/**
 * load whatever properties that already exist.
 */
private void loadproperties() {
//在这里修改一些连接参数
//in 2000
/*
string driver="org.gjt.mm.mysql.driver";
string server="jdbc:mysql://192.100.100.11/pcc";
string username="pcc";
string password="pcc123";
string minconnections="3";
string maxconnections="10";
string logpath="c:\\temp\\qingtuodblog.log";
string connectiontimeout="0.5";
*/
//in linux

string driver="org.gjt.mm.mysql.driver";
string server="jdbc:mysql://192.100.100.1/qingtuo";
//string server="jdbc:mysql://192.168.0.1/qingtuo";
string username="qingtuo";
string password="qingtuo";
string minconnections="3";
string maxconnections="20";
string logpath="c:\\temp\\qingtuodblog.log";
// string logpath="/tmp/qingtuodblog.log";
string connectiontimeout="0.5";


if (driver != null) { props.setproperty("driver", driver); }
if (server != null) { props.setproperty("server", server); }
if (username != null) { props.setproperty("username", username); }
if (password != null) { props.setproperty("password", password); }
//if (database != null) { props.setproperty("database", database); }
if (minconnections != null) { props.setproperty("minconnections", minconnections); }
if (maxconnections != null) { props.setproperty("maxconnections", maxconnections); }
if (logpath != null) { props.setproperty("logpath", logpath); }
if (connectiontimeout != null) { props.setproperty("connectiontimeout", connectiontimeout); }
}

private void saveproperties() {
propertymanager.setproperty("dbconnectiondefaultpool.driver", props.getproperty("driver"));
propertymanager.setproperty("dbconnectiondefaultpool.server", props.getproperty("server"));
propertymanager.setproperty("dbconnectiondefaultpool.username", props.getproperty("username"));
propertymanager.setproperty("dbconnectiondefaultpool.password", props.getproperty("password"));
propertymanager.setproperty("dbconnectiondefaultpool.minconnections", props.getproperty("minconnections"));
propertymanager.setproperty("dbconnectiondefaultpool.maxconnections", props.getproperty("maxconnections"));
propertymanager.setproperty("dbconnectiondefaultpool.logpath", props.getproperty("logpath"));
propertymanager.setproperty("dbconnectiondefaultpool.connectiontimeout", props.getproperty("connectiontimeout"));
}

private class connectionpool implements runnable {
private thread runner;

private connection[] connpool;
private int[] connstatus;

private long[] connlocktime, conncreatedate;
private string[] connid;
private string dbdriver, dbserver, dblogin, dbpassword, logfilestring;
private int currconnections, connlast, minconns, maxconns, maxconnmsec;

//available: set to false on destroy, checked by getconnection()
private boolean available=true;

private printwriter log;
private sqlwarning currsqlwarning;
private string pid;

/**
 * creates a new connection broker<br>
 * dbdriver: jdbc driver. e.g. 'oracle.jdbc.driver.oracledriver'<br>
 * dbserver: jdbc connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'<br>
 * dblogin:  database login name. e.g. 'scott'<br>
 * dbpassword: database password. e.g. 'tiger'<br>
 * minconns: minimum number of connections to start with.<br>
 * maxconns: maximum number of connections in dynamic pool.<br>
 * logfilestring:  absolute path name for log file. e.g. 'c:\temp\mylog.log' <br>
 * maxconntime:  time in days between connection resets. (reset does a basic cleanup)<br>
 */
public connectionpool (string dbdriver, string dbserver, string dblogin,
string dbpassword, int minconns, int maxconns,
string logfilestring, double maxconntime) throws ioexception
{
connpool = new connection[maxconns];
connstatus = new int[maxconns];
connlocktime = new long[maxconns];
conncreatedate = new long[maxconns];
connid = new string[maxconns];
currconnections = minconns;
this.maxconns = maxconns;
this.dbdriver = dbdriver;
this.dbserver = dbserver;
this.dblogin = dblogin;
this.dbpassword = dbpassword;
this.logfilestring = logfilestring;
maxconnmsec = (int)(maxconntime * 86400000.0); //86400 sec/day
if(maxconnmsec < 30000) { // recycle no less than 30 seconds.
maxconnmsec = 30000;
}

try {
log = new printwriter(new fileoutputstream(logfilestring),true);

// can't open the requested file. open the default file.
}
catch (ioexception e1) {
system.err.println("warning: dbconnectiondefaultpool could not open \""
+ logfilestring + "\" to write log to. make sure that your java " +
"process has permission to write to the file and that the directory exists."
);
try {
log = new printwriter(new fileoutputstream("dcb_" +
system.currenttimemillis() + ".log"), true
);
}
catch (ioexception e2) {
throw new ioexception("can't open any log file");
}
}

// write the pid file (used to clean up dead/broken connection)
simpledateformat formatter
= new simpledateformat ("yyyy.mm.dd g 'at' hh:mm:ss a zzz");
java.util.date nowc = new java.util.date();
pid = formatter.format(nowc);

bufferedwriter pidout = new bufferedwriter(new
filewriter(logfilestring + "pid"));
pidout.write(pid);
pidout.close();

log.println("starting connectionpool:");
log.println("dbdriver = " + dbdriver);
log.println("dbserver = " + dbserver);
log.println("dblogin = " + dblogin);
log.println("log file = " + logfilestring);
log.println("minconnections = " + minconns);
log.println("maxconnections = " + maxconns);
log.println("total refresh interval = " + maxconntime + " days");
log.println("-----------------------------------------");


// initialize the pool of connections with the mininum connections:
// problems creating connections may be caused during reboot when the
// servlet is started before the database is ready. handle this
// by waiting and trying again. the loop allows 5 minutes for
// db reboot.
boolean connectionssucceeded=false;
int dbloop=20;

try {
for(int i=1; i < dbloop; i++) {
try {
for(int j=0; j < currconnections; j++) {
log.println("create conn "+j);
createconn(j);
}
connectionssucceeded=true;
break;
}
catch (sqlexception e){
log.println("--->attempt (" + string.valueof(i) +
" of " + string.valueof(dbloop) +
") failed to create new connections set at startup: ");
log.println(" " + e);
log.println(" will try again in 15 seconds...");
try { thread.sleep(15000); }
catch(interruptedexception e1) {}
}
}
if(!connectionssucceeded) { // all attempts at connecting to db exhausted
log.println("\r\nall attempts at connecting to database exhausted");
throw new ioexception();
}
}
catch (exception e) {
throw new ioexception();
}

// fire up the background housekeeping thread

runner = new thread(this);
runner.start();

} //end connectionpool()

//文件:dbconnectiondefaultpool.java的第二部分


/**
 * housekeeping thread. runs in the background with low cpu overhead.
 * connections are checked for warnings and closure and are periodically
 * restarted.
 * this thread is a catchall for corrupted
 * connections and prevents the buildup of open cursors. (open cursors
 * result when the application fails to close a statement).
 * this method acts as fault tolerance for bad connection/statement programming.
 */
public void run() {
boolean forever = true;
statement stmt=null;
string currcatalog=null;

while(forever) {

// make sure the log file is the one this instance opened
// if not, clean it up!
try {
bufferedreader in = new bufferedreader(new
filereader(logfilestring + "pid"));
string curr_pid = in.readline();
if(curr_pid.equals(pid)) {
//log.println("they match = " + curr_pid);
}
else {
//log.println("no match = " + curr_pid);
log.close();

// close all connections silently - they are definitely dead.
for(int i=0; i < currconnections; i++) {
try {
connpool[i].close();
}
catch (sqlexception e1) {} // ignore
}
// returning from the run() method kills the thread
return;
}
in.close();
}
catch (ioexception e1) {
log.println("can't read the file for pid info: " +
logfilestring + "pid");
}

// get any warnings on connections and print to event file
for(int i=0; i < currconnections; i++) {
try {
currsqlwarning = connpool[i].getwarnings();
if(currsqlwarning != null) {
log.println("warnings on connection " +
string.valueof(i) + " " + currsqlwarning);
connpool[i].clearwarnings();
}
}
catch(sqlexception e) {
log.println("cannot access warnings: " + e);
}
}

for(int i=0; i < currconnections; i++) { // do for each connection
long age = system.currenttimemillis() - conncreatedate[i];

synchronized(connstatus) {
if(connstatus[i] > 0) { // in use, catch it next time!
continue;
}
connstatus[i] = 2; // take offline (2 indicates housekeeping lock)
}

try { // test the connection with createstatement call
if(age > maxconnmsec) { // force a reset at the max conn time
throw new sqlexception();
}

stmt = connpool[i].createstatement();
connstatus[i] = 0; // connection is o.k.
//log.println("connection confirmed for conn = " +
//  string.valueof(i));

// some dbs return an object even if db is shut down
if(connpool[i].isclosed()) {
throw new sqlexception();
}
// connection has a problem, restart it
}
catch(sqlexception e) {
try {
log.println(new date().tostring() +
" ***** recycling connection " +
string.valueof(i) + ":");

connpool[i].close();
createconn(i);
}
catch(sqlexception e1) {
log.println("failed: " + e1);
connstatus[i] = 0; // can't open, try again next time
}
}
finally {
try {
if(stmt != null) {
stmt.close();
}
}
catch(sqlexception e1){};
}
}

try {
thread.sleep(20000);
} // wait 20 seconds for next cycle
catch(interruptedexception e) {
// returning from the run method sets the internal
// flag referenced by thread.isalive() to false.
// this is required because we don't use stop() to
// shutdown this thread.
return;
}
}
} // end run
 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:一个连接池的例子 (二)
· 下一篇:JSP/Servlet构建三层管理信息系统
· JSP安全性初探
· j2ee的jdbc配置指南--连接sql server 数据库
· 四、处理表单数据
· 一、Servlet和JSP概述
· JSP由浅入深(1)


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077