网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  一个连接池的例子(来自jive)     
  文章作者:未知  文章来源:水木森林  
  查看:100次  录入:管理员--2007-11-17  
 
  作者:sonymusic
email: sonymusic@china.com
//文件: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: empmylog.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(" all 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

/**
* this method hands out the connections in round-robin order.
* this prevents a faulty connection from locking
* up an application entirely. a browser ′refresh′ will
* get the next connection while the faulty
* connection is cleaned up by the housekeeping thread.
*
* if the min number of threads are ever exhausted, new
* threads are added up the the max thread count.
* finally, if all threads are in use, this method waits
* 2 seconds and tries again, up to ten times. after that, it
* returns a null.
*/
public connection getconnection() {

connection conn=null;

if(available){
boolean gotone = false;

for(int outerloop=1; outerloop<=10; outerloop++) {

try {
int loop=0;
int roundrobin = connlast + 1;
if(roundrobin >= currconnections) roundrobin=0;

do {
synchronized(connstatus) {
if((connstatus[roundrobin] < 1) &&
(! connpool[roundrobin].isclosed()))
{
conn = connpool[roundrobin];
connstatus[roundrobin]=1;
connlocktime[roundrobin] =
system.currenttimemillis();
connlast = roundrobin;
gotone = true;
break;
}
else {
loop++;
roundrobin++;
if(roundrobin >= currconnections) roundrobin=0;
}
}
}
while((gotone==false)&&(loop < currconnections));
}
catch (sqlexception e1) {}

if(gotone) {
break;
}
else {
synchronized(this) { // add new connections to the pool
if(currconnections < maxconns) {
try {
createconn(currconnections);
currconnections++;
}
catch(sqlexception e) {
log.println("unable to create new connection: " + e);
}
}
}

try { thread.sleep(2000); }
catch(interruptedexception e) {}
log.println("-----> connections exhausted! will wait and try " +
"again in loop " +
string.valueof(outerloop));
}
} // end of try 10 times loop

}
else {
log.println("unsuccessful getconnection() request during destroy()");
} // end if(available)

return conn;
}

/**
* returns the local jdbc id for a connection.
*/
public int idofconnection(connection conn) {
int match;
string tag;

try {
tag = conn.tostring();
}
catch (nullpointerexception e1) {
tag = "none";
}

match=-1;

for(int i=0; i< currconnections; i++) {
if(connid[i].equals(tag)) {
match = i;
break;
}
}
return match;
}

/**
* frees a connection. replaces connection back into the main pool for
* reuse.
*/
public string freeconnection(connection conn) {
string res="";

int thisconn = idofconnection(conn);
if(thisconn >= 0) {
connstatus[thisconn]=0;
res = "freed " + conn.tostring();
//log.println("freed connection " + string.valueof(thisconn) +
// " normal exit: ");
}
else {
log.println("----> could not free connection!!!");
}

return res;
}

//文件:dbconnectiondefaultpool.java的第三部分
/**
* returns the age of a connection -- the time since it was handed out to
* an application.
*/
public long getage(connection conn) { // returns the age of the connection in millisec.
int thisconn = idofconnection(conn);
return system.currenttimemillis() - connlocktime[thisconn];
}

private void createconn(int i) throws sqlexception {
date now = new date();
try {
class.forname (dbdriver);
properties dbprop = new properties();
//log.println("creating.....");
dbprop.put("user", dblogin);
dbprop.put("password", dbpassword);
dbprop.put("characterencoding","gb2112");
//dbprop.put("useunicode", "true");

connpool[i] = drivermanager.getconnection
(dbserver,dbprop);
//log.println("created ok...");
connstatus[i]=0;
connid[i]=connpool[i].tostring();
connlocktime[i]=0;
conncreatedate[i] = now.gettime();
}
catch (classnotfoundexception e2) {}

log.println(now.tostring() + " opening connection " + string.valueof(i) +
" " + connpool[i].tostring() + ":");
}

/**
* shuts down the housekeeping thread and closes all connections
* in the pool. call this method from the destroy() method of the servlet.
*/

/**
* multi-phase shutdown. having following sequence:
* <ol>
* <li><code>getconnection()</code> will refuse to return connections.
* <li>the housekeeping thread is shut down.<br>
* up to the time of <code>millis</code> milliseconds after shutdown of
* the housekeeping thread, <code>freeconnection()</code> can still be
* called to return used connections.
* <li>after <code>millis</code> milliseconds after the shutdown of the
* housekeeping thread, all connections in the pool are closed.
* <li>if any connections were in use while being closed then a
* <code>sqlexception</code> is thrown.
* <li>the log is closed.
* </ol><br>
* call this method from a servlet destroy() method.
*
* @param millis the time to wait in milliseconds.
* @exception sqlexception if connections were in use after
* <code>millis</code>.
*/
public void destroy(int millis) throws sqlexception {

// checking for invalid negative arguments is not necessary,
// thread.join() does this already in runner.join().

// stop issuing connections
available=false;

// shut down the background housekeeping thread
runner.interrupt();

// wait until the housekeeping thread has died.
try { runner.join(millis); }
catch(interruptedexception e){} // ignore

// the housekeeping thread could still be running
// (e.g. if millis is too small). this case is ignored.
// at worst, this method will throw an exception with the
// clear indication that the timeout was too short.

long starttime=system.currenttimemillis();

// wait for freeconnection() to return any connections
// that are still used at this time.
int usecount;
while((usecount=getusecount())>0 && system.currenttimemillis() - starttime <= millis) {
try { thread.sleep(500); }
catch(interruptedexception e) {} // ignore
}

// close all connections, whether safe or not
for(int i=0; i < currconnections; i++) {
try {
connpool[i].close();
}
catch (sqlexception e1)
{
log.println("cannot close connections on destroy");
}
}

if(usecount > 0) {
//bt-test successful
string msg="unsafe shutdown: had to close "+usecount+
" active db connections after "+millis+"ms";
log.println(msg);
// close all open files
log.close();
// throwing following exception is essential because servlet authors
// are likely to have their own error logging requirements.
throw new sqlexception(msg);
}

// close all open files
log.close();

}//end destroy()

/**
* less safe shutdown. uses default timeout value.
* this method simply calls the <code>destroy()</code> method
* with a <code>millis</code>
* value of 10000 (10 seconds) and ignores <code>sqlexception</code>
* thrown by that method.
* @see #destroy(int)
*/
public void destroy() {
try {
destroy(10000);
}
catch(sqlexception e) {}
}

/**
* returns the number of connections in use.
*/
// this method could be reduced to return a counter that is
// maintained by all methods that update connstatus.
// however, it is more efficient to do it this way because:
// updating the counter would put an additional burden on the most
// frequently used methods; in comparison, this method is
// rarely used (although essential).
public int getusecount() {
int usecount=0;
synchronized(connstatus) {
for(int i=0; i < currconnections; i++) {
if(connstatus[i] > 0) { // in use
usecount++;
}
}
}
return usecount;
}//end getusecount()

/**
* returns the number of connections in the dynamic pool.
*/
public int getsize() {
return currconnections;
}//end getsize()

}

/**
* an implementation of the connection interface that wraps an underlying
* connection object. it releases the connection back to a connection pool
* when connection.close() is called.
*/
public class connectionwrapper implements connection {

private connection connection;
private connectionpool connectionpool;

public connectionwrapper(connection connection, connectionpool connectionpool) {
this.connection = connection;
this.connectionpool = connectionpool;
}

/**
* instead of closing the underlying connection, we simply release
* it back into the pool.
*/
public void close() throws sqlexception {
connectionpool.freeconnection(this.connection);
//release object references. any further method calls on the
//connection will fail.
connection = null;
connectionpool = null;
}

public statement createstatement() throws sqlexception {
return connection.createstatement();
}

public preparedstatement preparestatement(string sql) throws sqlexception {
return connection.preparestatement(sql);
}

public callablestatement preparecall(string sql) throws sqlexception {
return connection.preparecall(sql);
}

public string nativesql(string sql) throws sqlexception {
return connection.nativesql(sql);
}

public void setautocommit(boolean autocommit) throws sqlexception {
connection.setautocommit(autocommit);
}

public boolean getautocommit() throws sqlexception {
return connection.getautocommit();
}

public void commit() throws sqlexception {
connection.commit();
}

public void rollback() throws sqlexception {
connection.rollback();
}

public boolean isclosed() throws sqlexception {
return connection.isclosed();
}

public databasemetadata getmetadata() throws sqlexception {
return connection.getmetadata();
}

public void setreadonly(boolean readonly) throws sqlexception {
connection.setreadonly(readonly);
}

public boolean isreadonly() throws sqlexception {
return connection.isreadonly();
}

public void setcatalog(string catalog) throws sqlexception {
connection.setcatalog(catalog);
}

public string getcatalog() throws sqlexception {
return connection.getcatalog();
}

public void settransactionisolation(int level) throws sqlexception {
connection.settransactionisolation(level);
}

public int gettransactionisolation() throws sqlexception {
return connection.gettransactionisolation();
}

public sqlwarning getwarnings() throws sqlexception {
return connection.getwarnings();
}

public void clearwarnings() throws sqlexception {
connection.clearwarnings();
}

public statement createstatement(int resultsettype, int resultsetconcurrency)
throws sqlexception
{
return connection.createstatement(resultsettype, resultsetconcurrency);
}

public preparedstatement preparestatement(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return connection.preparestatement(sql, resultsettype, resultsetconcurrency);
}

public callablestatement preparecall(string sql, int resultsettype,
int resultsetconcurrency) throws sqlexception
{
return preparecall(sql, resultsettype, resultsetconcurrency);
}

public map gettypemap() throws sqlexception {
return connection.gettypemap();
}

public void settypemap(map map) throws sqlexception {
connection.settypemap(map);
}

}
}

//文件:dbconnectionmanager.java
package com.qingtuo.db.pool;

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

/**
* central manager of database connections.
*/
public class dbconnectionmanager {

private static dbconnectionprovider connectionprovider;
private static object providerlock = new object();

/**
* returns a database connection from the currently active connection
* provider.
*/
public static connection getconnection() {
if (connectionprovider == null) {
synchronized (providerlock) {
if (connectionprovider == null) {
//create the connection provider -- for now, this is hardcoded. for
//the next beta, i′ll change this to load up the provider dynamically.
connectionprovider = new dbconnectiondefaultpool();
connectionprovider.start();
}
}
}
connection con = connectionprovider.getconnection();
if (con == null) {
system.err.println("warning: dbconnectionmanager.getconnection() failed to obtain a connection.");
}
return con;
}

/**
* returns the current connection provider. the only case in which this
* method should be called is if more information about the current
* connection provider is needed. database connections should always be
* obtained by calling the getconnection method of this class.
*/
public static dbconnectionprovider getdbconnectionprovider() {
return connectionprovider;
}

/**
* sets the connection provider. the old provider (if it exists) is shut
* down before the new one is started. a connection provider <b>should
* not</b> be started before being passed to the connection manager.
*/
public static void setdbconnectionprovider(dbconnectionprovider provider) {
synchronized (providerlock) {
if (connectionprovider != null) {
connectionprovider.destroy();
connectionprovider = null;
}
connectionprovider = provider;
provider.start();
}
}

}

//文件:dbconnectionprovider.java
package com.qingtuo.db.pool;

import java.sql.*;
import java.util.*;

public abstract class dbconnectionprovider {

/** dummy values. override in subclasses. **/
private static final string name = "";
private static final string description = "";
private static final string author = "";
private static final int major_version = 0;
private static final int minor_version = 0;
private static final boolean pooled = false;

/**
* returns the name of the connection provider.
*/
public string getname() {
return name;
}

/**
* returns a description of the connection provider.
*/
public string getdescription() {
return description;
}

/**
* returns the author of the connection provider.
*/
public string getauthor() {
return author;
}

/**
* returns the major version of the connection provider, i.e. the 1 in 1.0.
*/
public int getmajorversion() {
return major_version;
}

public int getminorversion() {

return minor_version;

}

/**
* returns true if this connection provider provides connections out
* of a connection pool.
*/
public boolean ispooled() {
return pooled;
}

/**
* returns a database connection. when a jive component is done with a
* connection, it will call the close method of that connection. therefore,
* connection pools with special release methods are not directly
* supported by the connection provider infrastructure. instead, connections
* from those pools should be wrapped such that calling the close method
* on the wrapper class will release the connection from the pool.
*/
public abstract connection getconnection();

/**
* starts the connection provider. for some connection providers, this
* will be a no-op. however, connection provider users should always call
* this method to make sure the connection provider is started.
*/
protected abstract void start();

/**
* this method should be called whenever properties have been changed so
* that the changes will take effect.
*/
protected abstract void restart();

/**
* tells the connection provider to destroy itself. for many connection
* providers, this will essentially result in a no-op. however,
* connection provider users should always call this method when changing
* from one connection provider to another to ensure that there are no
* dangling database connections.
*/
protected abstract void destroy();

/**
* returns the value of a property of the connection provider.
*
* @param name the name of the property.
* @returns the value of the property.
*/
public abstract string getproperty(string 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 abstract string getpropertydescription(string name);

/**
* returns an enumeration of the property names for the connection provider.
*/
public abstract enumeration 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 abstract void setproperty(string name, string value);

}

//文件:propertymanager.java
//这个类其实没什么用了,可以去掉,但需要去掉前面几个类中对这个类的引用。
package com.qingtuo.db.pool;

import java.util.*;
import java.io.*;

/**
* manages properties for the entire jive system. properties are merely
* pieces of information that need to be saved in between server restarts.
* <p>
* at the moment, properties are stored in a java properties file. in a version
* of jive coming soon, the properties file format will move to xml. xml
* properties will allow hierarchical property structures which may mean the
* api of this class will have to change.
* <p>
* jive properties are only meant to be set and retrevied by core jive classes.
* therefore, skin writers should probably ignore this class.
* <p>
* this class is implemented as a singleton since many classloaders seem to
* take issue with doing classpath resource loading from a static context.
*/
public class propertymanager {

private static propertymanager manager = null;
private static object managerlock = new object();
private static string propsname = "/pcc_2000.properties";

/**
* returns a jive property
*
* @param name the name of the property to return.
* @returns the property value specified by name.
*/
public static string getproperty(string name) {
if (manager == null) {
synchronized(managerlock) {
if (manager == null) {
string sysname=system.getproperty("os.name").touppercase();
if(sysname.indexof("win")!=-1){
propsname=propsname2000;
}
else{
propsname=propsnamelinux;
}
manager = new propertymanager(propsname);
}
}
}
return manager.getprop(name);
}

/**
* sets a jive property.
*
* @param name the name of the property being set.
* @param value the value of the property being set.
*/
public static void setproperty(string name, string value) {
if (manager == null) {
synchronized(managerlock) {
if (manager == null) {
manager = new propertymanager(propsname);
}
}
}
manager.setprop(name, value);
}

/**
* returns true if the properties are readable. this method is mainly
* valuable at setup time to ensure that the properties file is setup
* correctly.
*/
public static boolean propertyfileisreadable() {
if (manager == null) {
synchronized(managerlock) {
if (manager == null) {
manager = new propertymanager(propsname);
}
}
}
return manager.propfileisreadable();
}

/**
* returns true if the properties are writable. this method is mainly
* valuable at setup time to ensure that the properties file is setup
* correctly.
*/
public static boolean propertyfileiswritable() {
if (manager == null) {
synchronized(managerlock) {
if (manager == null) {
manager = new propertymanager(propsname);
}
}
}
return manager.propfileiswritable();
}

/**
* returns true if the jive.properties file exists where the path property
* purports that it does.
*/
public static boolean propertyfileexists() {
if (manager == null) {
synchronized(managerlock) {
if (manager == null) {
manager = new propertymanager(propsname);
}
}
}
return manager.propfileexists();
}

private properties properties = null;
private object propertieslock = new object();
private string resourceuri;

/**
* singleton access only.
*/
private propertymanager(string resourceuri) {
this.resourceuri = resourceuri;
}

/**
* gets a jive property. jive properties are stored in jive.properties.
* the properties file should be accesible from the classpath. additionally,
* it should have a path field that gives the full path to where the
* file is located. getting properties is a fast operation.
*/
public string getprop(string name) {
//if properties aren′t loaded yet. we also need to make this thread
//safe, so synchronize...
if (properties == null) {
synchronized(propertieslock) {
//need an additional check
if (properties == null) {
loadprops();
}
}
}
return properties.getproperty(name);
}

/**
* sets a jive property. because the properties must be saved to disk
* every time a property is set, property setting is relatively slow.
*/
public void setprop(string name, string value) {
//only one thread should be writing to the file system at once.
synchronized (propertieslock) {
//create the properties object if necessary.
if (properties == null) {
loadprops();
}
properties.setproperty(name, value);
//now, save the properties to disk. in order for this to work, the user
//needs to have set the path field in the properties file. trim
//the string to make sure there are no extra spaces.
string path = properties.getproperty("path").trim();
outputstream out = null;
try {
out = new fileoutputstream(path);
properties.store(out, "jive.properties -- " + (new java.util.date()));
}
catch (exception ioe) {
system.err.println("there was an error writing jive.properties to " + path + ". " +
"ensure that the path exists and that the jive process has permission " +
"to write to it -- " + ioe);
ioe.printstacktrace();
}
finally {
try {
out.close();
} catch (exception e) { }
}
}
}

/**
* loads jive properties from the disk.
*/
private void loadprops() {
properties = new properties();
inputstream in = null;
try {
in = getclass().getresourceasstream(resourceuri);
properties.load(in);
}
catch (ioexception ioe) {
system.err.println("error reading pcc properties" + ioe);
ioe.printstacktrace();
}
finally {
try {
in.close();
} catch (exception e) { }
}
}

/**
* returns true if the properties are readable. this method is mainly
* valuable at setup time to ensure that the properties file is setup
* correctly.
*/
public boolean propfileisreadable() {
try {
inputstream in = getclass().getresourceasstream(resourceuri);
return true;
}
catch (exception e) {
return false;
}
}

/**
* returns true if the jive.properties file exists where the path property
* purports that it does.
*/
public boolean propfileexists() {
string path = getprop("path");
file file = new file(path);
if (file.isfile()) {
return true;
}
else {
return false;
}
}

/**
* returns true if the properties are writable. this method is mainly
* valuable at setup time to ensure that the properties file is setup
* correctly.
*/
public boolean propfileiswritable() {
string path = getprop("path");
file file = new file(path);
if (file.isfile()) {
//see if we can write to the file
if (file.canwrite()) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}

private static string propsname2000 = "/pcc_2000.properties";
private static string propsnamelinux = "/pcc_linux.properties";
}

这个连接池是直接从jive中取出来的,进行了一下修改,使得连接参数直接在程序中设定而不是从属性文件中读取。

用法:
先设定自己的连接参数,在dbconnectiondefaultpool.java文件的loadproperties方法中。注意你也需要设定连接池的log文件的存放位置。

string driver="org.gjt.mm.mysql.driver";//这是使用的jdbc驱动
string server="jdbc:mysql://192.100.100.1/qingtuo";//使用的url
//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";//定时清除无用连接间隔(以天为单位)

[b]然后[/b]
在你的程序中只需要将这个包com.qingtuo.db.pool import进来,再向下面这样用就行了。

connection con = null;
preparedstatement pstmt = null;
resultset rs=null;
try {
con = dbconnectionmanager.getconnection();
//这里写你的sql语句
}
catch (sqlexception sqle) {
throw sqle;
}
finally {
try {
pstmt.close();
}
catch (exception e) {
e.printstacktrace();
}
try {
con.close();
}
catch (exception e) {
e.printstacktrace();
}
}

优点
虽然很多应用服务器也有连接池,但这样做的好处是,更加通用一些。
 
 
上一篇: 一个进行base64编码的类    下一篇: 一个浏览图片程序
  相关文档
新版junit 4.0 抢先体验 11-17
基于java的电子政务系统整体解决方案 11-16
java 中protected modifier 使用总结 11-17
对jsp数据库连接类使用方法的详细讲解 11-16
eclispe下开发struts完整解决乱码问题 01-09
linux 平台的 jvm 性能评测 11-17
驾驭“野马”--探索javase6的一些新特性 11-17
解析j2ee型式的应用(上) (1) 11-17
java学习:ejb的专用术语解释 11-16
java用oci驱连oracle数据库的实现方法 11-17
bea邮政行业rfid解决方案 11-17
spring framework中的aop编程之入门篇 11-16
java框架介绍:quartz从入门到进阶(图) 11-17
应用服务器的发展 11-17
[portal参考手册]目录 11-17
java几个常见错误简析(上) 11-16
preparedstatement 11-17
jsp语法 11-17
java excel api 简介 11-17
高级:编写多线程java应用程序常见问题 01-03
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
技术电话:13616026886
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息