/**
* @ Author Zhupan (gentle) creation date: 06-10-2006
*/
Package com. Zhupan. strutsarticle. utils;
Import java. SQL. connection;
Public class dbconnection {
Public static synchronized connection getconnection () throws exception {
Connection conn = NULL;
Dbconnectionmanager dBc;
Try {
DBC = dbconnectionmanager. getinstance ();
Conn = DBC. getconnection ("IDB ");
} Catch (exception e ){
}
Return conn;
}
}
/**
* @ Author Zhupan (gentle) creation date:
*/
Package com. Zhupan. strutsarticle. utils;
Import java. Io. filewriter;
Import java. Io. ioexception;
Import java. Io. inputstream;
Import java. Io. printwriter;
Import java. SQL. connection;
Import java. SQL. driver;
Import java. SQL. drivermanager;
Import java. SQL. sqlexception;
Import java. util. date;
Import java. util. enumeration;
Import java. util. hashtable;
Import java. util. properties;
Import java. util. stringtokenizer;
Import java. util. vector;
/** Connection pool
* Management class dbconnectionmanager supports connection to one or more databases defined by attribute files
* Pool access. The client program can call the getinstance () method to access the unique instance of this class.
*/
Public class dbconnectionmanager {
Static private dbconnectionmanager instance; // unique instance
Static private int clients;
Private vector drivers = new vector ();
Private printwriter log;
Private hashtable pools = new hashtable ();
/**
* A unique instance is returned. If this method is called for the first time, an instance is created.
*
* @ Return dbconnectionmanager: unique instance
*/
Static synchronized public dbconnectionmanager getinstance (){
If (instance = NULL ){
Instance = new dbconnectionmanager ();
}
Clients ++;
Return instance;
}
/**
* The construction function is private to prevent other objects from creating instances of this class.
*/
Private dbconnectionmanager (){
Init ();
}
/**
* Return the connection object to the connection pool specified by the name.
*
* @ Param name: name of the Connection Pool defined in the property File
* @ Param con connection object
*/
Public void freeconnection (string name, connection con ){
Dbconnectionpool pool = (dbconnectionpool) pools. Get (name );
If (pool! = NULL ){
Pool. freeconnection (CON );
}
}
/**
* Obtain an available (idle) connection. If there is no available connection, and the number of existing connections is less than the maximum number of connections
* Limit, a new connection is created and returned.
*
* @ Param name: name of the Connection Pool defined in the property File
* @ Return connection available connection or null
*/
Public connection getconnection (string name ){
Dbconnectionpool pool = (dbconnectionpool) pools. Get (name );
If (pool! = NULL ){
Return pool. getconnection ();
}
Return NULL;
}
/**
* Obtain an available connection. If no available connection is available and the number of existing connections is smaller than the maximum number of connections,
* A new connection is created and returned. Otherwise, wait for other threads to release the connection within the specified time.
*
* @ Param name connection pool name
* @ Param time the wait time in milliseconds
* @ Return connection available connection or null
*/
Public connection getconnection (string name, long time ){
Dbconnectionpool pool = (dbconnectionpool) pools. Get (name );
If (pool! = NULL ){
Return pool. getconnection (time );
}
Return NULL;
}
/**
* Close all connections and cancel the registration of the driver.
*/
Public synchronized void release (){
// Wait until the last client program is called
If (-- clients! = 0 ){
Return;
}
Enumeration allpools = pools. Elements ();
While (allpools. hasmoreelements ()){
Dbconnectionpool pool = (dbconnectionpool) allpools. nextelement ();
Pool. Release ();
}
Enumeration alldrivers = drivers. Elements ();
While (alldrivers. hasmoreelements ()){
Driver driver = (driver) alldrivers. nextelement ();
Try {
Drivermanager. deregisterdriver (driver );
Log ("revoking the JDBC driver" + driver. getclass (). getname () + "Registration ");
}
Catch (sqlexception e ){
Log (E, "Registration of the following JDBC drivers cannot be revoked:" + driver. getclass (). getname ());
}
}
}
/**
* Create a connection pool instance based on the specified attributes.
*
* @ Param props connection pool attributes (gentle)
*/
Private void createpools (properties props ){
Enumeration propnames = props. propertynames ();
While (propnames. hasmoreelements ()){
String name = (string) propnames. nextelement ();
If (name. endswith (". url ")){
String poolname = Name. substring (0, name. lastindexof ("."));
String url = props. getproperty (poolname + ". url ");
If (url = NULL ){
Log ("not specified URL for connection pool" + poolname + ");
Continue;
}
String user = props. getproperty (poolname + ". User ");
String Password = props. getproperty (poolname + ". Password ");
String maxconn = props. getproperty (poolname + ". maxconn", "0 ");
Int Max;
Try {
Max = integer. valueof (maxconn). intvalue ();
}
Catch (numberformatexception e ){
Log ("Maximum number of wrong connections limit:" + maxconn + ". Connection Pool:" + poolname );
Max = 0;
}
Dbconnectionpool =
New dbconnectionpool (poolname, URL, user, password, max );
Pools. Put (poolname, pool );
Log ("successfully created connection pool" + poolname );
}
}
}
/**
* Initialize the read attribute (gentle)
*/
Private void Init (){
Inputstream is = getclass (). getresourceasstream ("DB. properties ");
Properties dbprops = new properties ();
Try {
Dbprops. Load (is );
}
Catch (exception e ){
System. Err. println ("attribute files cannot be read." +
"Make sure that dB. properties is in the path specified by classpath ");
Return;
}
String logfile = dbprops. getproperty ("logfile", "dbconnectionmanager. log ");
Try {
Log = new printwriter (New filewriter (logfile, true), true );
}
Catch (ioexception e ){
System. Err. println ("log file cannot be opened:" + logfile );
Log = new printwriter (system. Err );
}
Loaddrivers (dbprops );
Createpools (dbprops );
}
/**
* Load and register all JDBC drivers (gentle)
*
* @ Param props attributes
*/
Private void loaddrivers (properties props ){
String driverclasses = props. getproperty ("drivers ");
Stringtokenizer ST = new stringtokenizer (driverclasses );
While (St. hasmoreelements ()){
String driverclassname = ST. nexttoken (). Trim ();
Try {
Driver driver = (driver)
Class. forname (driverclassname). newinstance ();
Drivermanager. registerdriver (driver );
Drivers. addelement (driver );
Log ("successfully registered JDBC driver" + driverclassname );
}
Catch (exception e ){
Log ("unable to register JDBC driver:" +
Driverclassname + ", error:" + E );
}
}
}
/**
* Write text information to a log file (gentle)
*/
Private void log (string MSG ){
Log. println (new date () + ":" + MSG );
}
/**
* Write text information and exceptions to log files (gentle)
*/
Private void log (throwable E, string MSG ){
Log. println (new date () + ":" + MSG );
E. printstacktrace (log );
}
/**
* This internal class defines a connection pool. It can create new connections as required until the predefined
* Until the number of connections reaches. It can verify the connection validity before returning the connection to the client program. (gentle)
*/
Class dbconnectionpool {
Private int checkedout;
Private vector freeconnections = new vector ();
Private int maxconn;
Private string name;
Private string password;
Private string URL;
Private string user;
/**
* Create a new connection pool
*
* @ Param name connection pool name
* @ Param url jdbc url of the database
* @ Param User: database account, or null
* @ Param Password, or null (gentle)
* @ Param maxconn the maximum number of connections allowed in the connection pool
*/
Public dbconnectionpool (string name, string URL, string user, string password,
Int maxconn ){
This. Name = Name;
This. url = URL;
This. User = user;
This. Password = password;
This. maxconn = maxconn;
}
/**
* Return unused connections to the connection pool (gentle)
*
* @ Param con the connection released by the client program
*/
Public synchronized void freeconnection (connection con ){
// Add the specified join to the end of the Vector
Freeconnections. addelement (CON );
Checkedout --;
Policyall ();
}
/**
* Obtain an available connection from the connection pool. If there is no idle connection and the current number of connections is smaller than the maximum number of connections
* When the number limit is reached, a new connection will be created. If the previously registered available connection is no longer valid, it will be deleted from the vector,
* Then recursively call yourself to try new available connections (gentle)
*/
Public synchronized connection getconnection (){
Connection con = NULL;
If (freeconnections. Size ()> 0 ){
// Obtain the first available connection in the vector
Con = (connection) freeconnections. firstelement ();
Freeconnections. removeelementat (0 );
Try {
If (con. isclosed ()){
Log ("deleting an invalid connection from the connection pool" + name + ");
// Call yourself recursively and try to obtain available connections again
Con = getconnection ();
}
}
Catch (sqlexception e ){
Log ("deleting an invalid connection from the connection pool" + name + ");
// Call yourself recursively and try to obtain available connections again
Con = getconnection ();
}
}
Else if (maxconn = 0 | checkedout <maxconn ){
Con = newconnection ();
}
If (con! = NULL ){
Checkedout ++;
}
Return con;
}
/**
* Obtain available connections from the connection pool. You can specify the maximum waiting time for the client program.
* See the previous getconnection () method.
*
* @ Param timeout the wait time limit in milliseconds
*/
Public synchronized connection getconnection (long timeout ){
Long starttime = new date (). gettime ();
Connection con;
While (con = getconnection () = NULL ){
Try {
Wait (timeout );
}
Catch (interruptedexception e ){}
If (new date (). gettime ()-starttime)> = timeout ){
// Wait () returns timeout.
Return NULL;
}
}
Return con;
}
/**
* Close all connections (gentle)
*/
Public synchronized void release (){
Enumeration allconnections = freeconnections. Elements ();
While (allconnections. hasmoreelements ()){
Connection con = (connection) allconnections. nextelement ();
Try {
Con. Close ();
Log ("close a connection pool" + name + "in a connection pool ");
}
Catch (sqlexception e ){
Log (E, "unable to close connections in connection pool" + name + ");
}
}
Freeconnections. removeallelements ();
}
/**
* Create a new connection (gentle)
*/
Private connection newconnection (){
Connection con = NULL;
Try {
If (user = NULL ){
Con = drivermanager. getconnection (URL );
}
Else {
Con = drivermanager. getconnection (URL, user, password );
}
Log ("connection pool" + name + "Create a new connection ");
}
Catch (sqlexception e ){
Log (E, "cannot create the following URL Connection:" + URL );
Return NULL;
}
Return con;
}
}
}
DB. properties file (gentle)
Drivers = com. MySQL. JDBC. Driver
Logfile = C: // strutsarticle. Log
IDB. url = JDBC: mysql: // localhost/strutsarticle? Useunicode = true & characterencoding = gb2312
IDB. maxconn = 100
IDB. User = root
IDB. Password =