| |
作者: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(); } }
优点 虽然很多应用服务器也有连接池,但这样做的好处是,更加通用一些。
|
|