发信人: huanghwh(五云人)
整理人: zjxyz(2003-02-23 14:59:14), 站内信件
|
【 在 liuzhenai 的大作中提到:】
:
:连接池,可以提高JSP程序的效率,jsp使用连接池是很有必要的,但是兄弟我对连接池还知之甚少,请哪位老兄用精简、通俗的语言给我补一课,谢谢!!
:
:1、从本质上讲,连接池到底有什么作用(主要结合jsp,mssql/oracle)?
:2、从形式上讲,连接池的使用,需要掌哪几个类?(最好举个例,这样会清楚很多)
:
:......
part two
/**
* <p>Loads the given configuration file. All global
* properties (such as JDBCDriver) will be
* read and removed from the properties list. Any leftover
* properties will be returned. Returns null if the
* properties could not be loaded
*
* @param name Configuration file name
* @return true if the configuration file was loaded
*/
private boolean loadConfig(String name)
throws Exception
{
boolean rc = false;
// Get our class loader
ClassLoader cl = getClass().getClassLoader();
// Attempt to open an input stream to the configuration file.
// The configuration file is considered to be a system
// resource.
java.io.InputStream in;
if (cl != null) {
in = cl.getResourceAsStream(name);
}
else {
in = ClassLoader.getSystemResourceAsStream(name);
}
if (in == null) { //use normal FileInpustream
in = new FileInputStream(name);
}
// If the input stream is null, then the configuration file
// was not found
if(in == null)
throw new Exception("ConnectionPool configuration file '" +
name + "' not found");
else {
try {
m_JDBCProperties = new java.util.Properties();
java.util.Properties allProperties = new java.util.Properties();
allProperties.load(in);
// Load the configuration file into the properties table
//m_JDBCProperties.load(in);
//fill m_JDBCProperties
m_JDBCProperties.put("JDBCDriver", allProperties.getProperty("JDBCDriver"));
m_JDBCProperties.put("JDBCConnectionURL", allProperties.getProperty("JDBCConnectionURL"));
m_JDBCProperties.put("ConnectionPoolSize", allProperties.getProperty("ConnectionPoolSize"));
m_JDBCProperties.put("ConnectionPoolMax", allProperties.getProperty("ConnectionPoolMax"));
m_JDBCProperties.put("ConnectionTimeout", allProperties.getProperty("ConnectionTimeout"));
m_JDBCProperties.put("ConnectionUseCount", allProperties.getProperty("ConnectionUseCount"));
m_JDBCProperties.put("User", allProperties.getProperty("User"));
m_JDBCProperties.put("Password", allProperties.getProperty("Password"));
allProperties.clear();
// Got the properties. Pull out the properties that we
// are interested in
m_JDBCDriver = consume(m_JDBCProperties, "JDBCDriver");
m_JDBCConnectionURL = consume(m_JDBCProperties,
"JDBCConnectionURL");
m_ConnectionPoolSize = consumeInt(m_JDBCProperties,
"ConnectionPoolSize");
m_ConnectionPoolMax = consumeInt(m_JDBCProperties,
"ConnectionPoolMax");
m_ConnectionTimeout = consumeInt(m_JDBCProperties,
"ConnectionTimeout");
m_ConnectionUseCount = consumeInt(m_JDBCProperties,
"ConnectionUseCount");
rc = true;
}
finally {
// Always close the input stream
if (in != null) {
try {
in.close();
}
catch (Exception ex) {
}
}
}
}
return rc;
}
/**
* <p>Consumes the given property and returns the value.
*
* @param properties Properties table
* @param key Key of the property to retrieve and remove from
* the properties table
* @return Value of the property, or null if not found
*/
private String consume(java.util.Properties p, String key)
{
String s = null;
if ((p != null) &&
(key != null)) {
// Get the value of the key
s = p.getProperty(key);
// If found, remove it from the properties table
if (s != null) {
p.remove(key);
}
}
return s;
}
/**
* <p>Consumes the given property and returns the integer
* value.
*
* @param properties Properties table
* @param key Key of the property to retrieve and remove from
* the properties table
* @return Value of the property, or -1 if not found
*/
private int consumeInt(java.util.Properties p, String key)
{
int n = -1;
// Get the String value
String value = consume(p, key);
// Got a value; convert to an integer
if (value != null) {
try {
n = Integer.parseInt(value);
}
catch (Exception ex) {
}
}
return n;
}
/**
* <p>Creates the initial connection pool. A timer thread
* is also created so that connection timeouts can be
* handled.
*
* @return true if the pool was created
*/
private void createPool() throws Exception
{
// Sanity check our properties
if (m_JDBCDriver == null) {
throw new Exception("JDBCDriver property not found");
}
if (m_JDBCConnectionURL == null) {
throw new Exception("JDBCConnectionURL property not found");
}
if (m_ConnectionPoolSize < 0) {
throw new Exception("ConnectionPoolSize property not found");
}
if (m_ConnectionPoolSize == 0) {
throw new Exception("ConnectionPoolSize invalid");
}
if (m_ConnectionPoolMax < m_ConnectionPoolSize) {
trace("WARNING - ConnectionPoolMax is invalid and will " +
"be ignored");
m_ConnectionPoolMax = -1;
}
if (m_ConnectionTimeout < 0) {
// Set the default to 30 minutes
m_ConnectionTimeout = 30;
}
// Dump the parameters we are going to use for the pool.
// We don't know what type of servlet environment we will
// be running in - this may go to the console or it
// may be redirected to a log file
//trace("JDBCDriver = " + m_JDBCDriver);
//trace("JDBCConnectionURL = " + m_JDBCConnectionURL);
//trace("ConnectionPoolSize = " + m_ConnectionPoolSize);
//trace("ConnectionPoolMax = " + m_ConnectionPoolMax);
//trace("ConnectionUseCount = " + m_ConnectionUseCount);
//trace("ConnectionTimeout = " + m_ConnectionTimeout +
// " seconds");
// Also dump any additional JDBC properties
java.util.Enumeration enum = m_JDBCProperties.keys();
while (enum.hasMoreElements()) {
String key = (String) enum.nextElement();
String value = m_JDBCProperties.getProperty(key);
//trace("(JDBC Property) " + key + " = " + value);
}
// Attempt to create a new instance of the specified
// JDBC driver. Well behaved drivers will register
// themselves with the JDBC DriverManager when they
// are instantiated
//trace("Registering " + m_JDBCDriver);
java.sql.Driver d = (java.sql.Driver)
Class.forName(m_JDBCDriver).newInstance();
// Create the vector for the pool
m_pool = new java.util.Vector();
// Bring the pool to the minimum size
fillPool(m_ConnectionPoolSize);
}
/**
* <p>Adds a new connection to the pool
*
* @return Index of the new pool entry, or -1 if an
* error has occurred
*/
private int addConnection()
{
int index = -1;
try {
// Calculate the new size of the pool
int size = m_pool.size() + 1;
// Create a new entry
fillPool(size);
// Set the index pointer to the new connection if one
// was created
if (size == m_pool.size()) {
index = size - 1;
}
}
catch (Exception ex) {
ex.printStackTrace();
}
return index;
}
/**
* <p>Brings the pool to the given size
*/
private synchronized void fillPool(int size) throws Exception
{
boolean useProperties = true;
String userID = null;
String password = null;
// If the only properties present are the user id and
// password, get the connection using them instead of
// the properties object
if (m_JDBCProperties != null) {
// Make sure there are only 2 properties, and they are
// the user id and password
if (m_JDBCProperties.size() == 2) {
userID =
getPropertyIgnoreCase(m_JDBCProperties, "user");
password =
getPropertyIgnoreCase(m_JDBCProperties, "password");
// If all we've got is a user id and password then
// don't use the properties
if ((userID != null) && (password != null)) {
useProperties = false;
}
}
}
// Loop while we need to create more connections
while (m_pool.size() < size) {
ConnectionObject co = new ConnectionObject();
// Create the connection
if (useProperties) {
co.con = DriverManager.getConnection(m_JDBCConnectionURL,
m_JDBCProperties);
}
else {
co.con = DriverManager.getConnection(m_JDBCConnectionURL,
userID, password);
}
// Do some sanity checking on the first connection in
// the pool
if (m_pool.size() == 0) {
// Get the maximum number of simultaneous connections
// as reported by the JDBC driver
java.sql.DatabaseMetaData md = co.con.getMetaData();
m_MaxConnections = md.getMaxConnections();
}
// Give a warning if the size of the pool will exceed
// the maximum number of connections allowed by the
// JDBC driver
if ((m_MaxConnections > 0) &&
(size > m_MaxConnections)) {
trace("WARNING: Size of pool will exceed safe maximum of " +
m_MaxConnections);
}
// Clear the in use flag
co.inUse = false;
// Set the last access time
touch(co);
m_pool.addElement(co);
}
}
/**
* Gets a the named propery, ignoring case. Returns null if
* not found
* @param p The property set
* @param name The property name
* @return The value of the propery, or null if not found
*/
private String getPropertyIgnoreCase(java.util.Properties p,
String name)
{
if ((p == null) || (name == null)) return null;
String value = null;
// Get an enumeration of the property names
java.util.Enumeration enum = p.propertyNames();
// Loop through the enum, looking for the given property name
while (enum.hasMoreElements()) {
String pName = (String) enum.nextElement();
if (pName.equalsIgnoreCase(name)) {
value = p.getProperty(pName);
break;
}
}
return value;
}
/**
* <p>Find the given connection in the pool
*
* @return Index into the pool, or -1 if not found
*/
private int find(java.sql.Connection con)
{
int index = -1;
// Find the matching Connection in the pool
if ((con != null) &&
(m_pool != null)) {
for (int i = 0; i < m_pool.size(); i++) {
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(i);
if (co.con == con) {
index = i;
break;
}
}
}
return index;
}
/**
* <p>Called by the timer each time a clock cycle expires.
* This gives us the opportunity to timeout connections
*/
public synchronized void TimerEvent(Object object)
{
// No pool means no work
if (m_pool == null) {
return;
}
// Get the current time in milliseconds
long now = System.currentTimeMillis();
// Check for any expired connections and remove them
for (int i = m_pool.size() - 1; i >= 0; i--) {
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(i);
// If the connection is not in use and it has not been
// used recently, remove it
if (!co.inUse) {
if ((m_ConnectionTimeout > 0) &&
(co.lastAccess +
(m_ConnectionTimeout * 1000) < now)) {
removeFromPool(i);
}
}
}
// Remove any connections that are no longer open
for (int i = m_pool.size() - 1; i >= 0; i--) {
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(i);
try {
// If the connection is closed, remove it from the pool
if (co.con.isClosed()) {
//trace("Connection closed unexpectedly");
removeFromPool(i);
}
}
catch (Exception ex) {
}
}
// Now ensure that the pool is still at it's minimum size
try {
if (m_pool != null) {
if (m_pool.size() < m_ConnectionPoolSize) {
fillPool(m_ConnectionPoolSize);
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* <p>Sets the last access time for the given ConnectionObject
*/
private void touch(ConnectionObject co)
{
if (co != null) {
co.lastAccess = System.currentTimeMillis();
}
}
/**
* <p>Trace the given string
*/
private void trace(String s)
{
System.out.println("ConnectionPool: " + s);
}
/**
* just for test
*/
public static void main(String[] args){
System.out.println(System.getProperty("user.dir"));
try {
ConnectionPool cPool = new ConnectionPool();
cPool.initialize("etc/ConnectionPool.cfg");
java.sql.Connection con = cPool.getConnection();
cPool.destroy();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
// This package-private class is used to represent a single
// connection object
class ConnectionObject
{
// The JDBC Connection
public java.sql.Connection con;
// true if this connection is currently in use
public boolean inUse;
// The last time (in milliseconds) that this connection was used
public long lastAccess;
// The number of times this connection has been used
public int useCount;
/**
* <p>Determine if the connection is available
*
* @return true if the connection can be used
*/
public boolean isAvailable()
{
boolean available = false;
try {
// To be available, the connection cannot be in use
// and must be open
if (con != null) {
if (!inUse &&
!con.isClosed()) {
available = true;
}
}
}
catch (Exception ex) {
}
return available;
}
/**
* <p>Convert the object contents to a String
*/
public String toString()
{
return "Connection=" + con.toString() + ",inUse=" + inUse +
",lastAccess=" + new Date(lastAccess) + ",useCount=" + useCount;
}
}
---- Power OS is FreeBSD.
Network is computing.
Java is network language.
Web is Application. |
|