分享
 
 
 

一个连接池的例子(来自JIVE)

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

作者: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";//定时清除无用连接间隔(以天为单位)

然后

在你的程序中只需要将这个包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();

}

}

优点

虽然很多应用服务器也有连接池,但这样做的好处是,更加通用一些。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有