Proxool老牌的数据库连接池了,褒贬不一,性能上还行。目前最新版本是0.9.1,相对之前版本的配置有些变动。这里以MySQL5为例做一个简单数据库连接池配置。
环境:
MySQL5.x
JDK1.5
Proxool 0.9.1
一、配置文件
proxool.xml
<?
xml
version
="1.0"
encoding
="UTF-8"
?>
< something-else-entirely >
< proxool >
< alias >ds </ alias >
<!-- 数据源的别名-->
< driver-url >jdbc:mysql://192.168.104.191:3306/testdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull </ driver-url >
<!-- url连接串-->
< driver-class >com.mysql.jdbc.Driver </ driver-class >
<!-- 驱动类-->
< driver-properties >
< property name ="user" value ="vcom" />
<!-- 用户名-->
< property name ="password" value ="vcom" />
<!-- 密码-->
</ driver-properties >
<!-- 是指在任一时刻,可以(同时)建立的最大连接数,也就是说,就是已经请求的、但还没可用的新连接数量-->
<simultaneous-build-throttle>10</simultaneous-build-throttle>
<!-- 最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 -->
< maximum-connection-count >100 </ maximum-connection-count >
<!-- 最小连接数(默认2个)-->
< minimum-connection-count >10 </ minimum-connection-count >
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒-->
< house-keeping-sleep-time >120000 </ house-keeping-sleep-time >
<!-- 最少保持的空闲连接数(默认2个)-->
< prototype-count >10 </ prototype-count >
<!-- 在使用之前测试-->
< test-before-use >true </ test-before-use >
<!-- 用于保持连接的测试语句 -->
< house-keeping-test-sql >select 1 </ house-keeping-test-sql >
</ proxool >
</ something-else-entirely >
< something-else-entirely >
< proxool >
< alias >ds </ alias >
<!-- 数据源的别名-->
< driver-url >jdbc:mysql://192.168.104.191:3306/testdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull </ driver-url >
<!-- url连接串-->
< driver-class >com.mysql.jdbc.Driver </ driver-class >
<!-- 驱动类-->
< driver-properties >
< property name ="user" value ="vcom" />
<!-- 用户名-->
< property name ="password" value ="vcom" />
<!-- 密码-->
</ driver-properties >
<!-- 是指在任一时刻,可以(同时)建立的最大连接数,也就是说,就是已经请求的、但还没可用的新连接数量-->
<simultaneous-build-throttle>10</simultaneous-build-throttle>
<!-- 最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 -->
< maximum-connection-count >100 </ maximum-connection-count >
<!-- 最小连接数(默认2个)-->
< minimum-connection-count >10 </ minimum-connection-count >
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒-->
< house-keeping-sleep-time >120000 </ house-keeping-sleep-time >
<!-- 最少保持的空闲连接数(默认2个)-->
< prototype-count >10 </ prototype-count >
<!-- 在使用之前测试-->
< test-before-use >true </ test-before-use >
<!-- 用于保持连接的测试语句 -->
< house-keeping-test-sql >select 1 </ house-keeping-test-sql >
</ proxool >
</ something-else-entirely >
粗体部分是变化部分,上面有详细说明!
二、测试类
package lavasoft;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.configuration.JAXPConfigurator;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.List;
import java.util.Properties;
/**
* 简单的JDBC工具类
*
* @author leizhimin 2009-11-23 17:35:26
*/
public class MyDB {
private static final Log log = LogFactory.getLog(MyDB. class);
private static final boolean useDBPool = true; //是否使用数据库连接池
private static String dburl = null;
private static String user = null;
private static String password = null;
private static Properties props = new Properties();
static {
init();
}
public static void init() {
if (useDBPool) {
try {
JAXPConfigurator.configure( "proxool.xml", false);
// JAXPConfigurator.configure("src/proxool.xml", false);
} catch (ProxoolException e) {
e.printStackTrace();
}
return;
}
try {
// props.load(new FileInputStream("/jdbc.properties"));
props.load(MyDB. class.getResourceAsStream( "/jdbc.properties"));
} catch (IOException e) {
log.error( "#ERROR# :系统加载sysconfig.properties配置文件异常,请检查!", e);
}
dburl = props.getProperty( "jdbc.url");
user = props.getProperty( "jdbc.username").trim();
password = props.getProperty( "jdbc.password").trim();
System.out.println(dburl);
System.out.println(user);
System.out.println(password);
//注册驱动类
try {
Class.forName(props.getProperty( "jdbc.driver"));
} catch (ClassNotFoundException e) {
log.error( "#ERROR# :加载数据库驱动异常,请检查!", e);
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws FileNotFoundException {
for ( int i = 0; i < 5; i++) {
Connection conn = getConnection();
System.out.println(conn == null ? "没连上" : "连上了");
// System.out.println("--------");
// closeConnection(conn);
}
}
/**
* 创建一个数据库连接
*
* @return 一个数据库连接
*/
public static Connection getConnection() {
Connection conn = null;
//根据连接池配置创建数据库连接
if (useDBPool) {
try {
conn = DriverManager.getConnection( "proxool.ds");
} catch (SQLException e) {
log.error( "#ERROR# :无法从数据库连接池获取到数据库连接!");
throw new RuntimeException(e);
}
return conn;
}
//根据JDBC配置创建数据库连接
try {
conn = DriverManager.getConnection(dburl, user, password);
} catch (SQLException e) {
log.error( "#ERROR# :创建数据库连接发生异常,请检查!", e);
throw new RuntimeException(e);
}
return conn;
}
/**
* 在一个数据库连接上执行一个静态SQL语句查询
*
* @param conn 数据库连接
* @param staticSql 静态SQL语句字符串
* @return 返回查询结果集ResultSet对象
*/
public static ResultSet executeQuery(Connection conn, String staticSql) {
ResultSet rs = null;
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
//执行SQL,并获取返回结果
rs = stmt.executeQuery(staticSql);
} catch (SQLException e) {
log.error( "#ERROR# :执行SQL语句出错,请检查!\n" + staticSql, e);
throw new RuntimeException(e);
}
return rs;
}
/**
* 在一个数据库连接上执行一个静态SQL语句
*
* @param conn 数据库连接
* @param staticSql 静态SQL语句字符串
*/
public static void executeSQL(Connection conn, String staticSql) {
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
//执行SQL,并获取返回结果
stmt.execute(staticSql);
} catch (SQLException e) {
log.error( "#ERROR# :执行SQL语句出错,请检查!\n" + staticSql, e);
throw new RuntimeException(e);
}
}
/**
* 在一个数据库连接上执行一批静态SQL语句
*
* @param conn 数据库连接
* @param sqlList 静态SQL语句字符串集合
*/
public static void executeBatchSQL(Connection conn, List<String> sqlList) {
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
for (String sql : sqlList) {
stmt.addBatch(sql);
}
//执行SQL,并获取返回结果
stmt.executeBatch();
} catch (SQLException e) {
log.error( "#ERROR# :执行批量SQL语句出错,请检查!", e);
}
}
public static void closeConnection(Connection conn) {
if (conn == null) return;
try {
if (!conn.isClosed()) {
//关闭数据库连接
conn.close();
}
} catch (SQLException e) {
log.error( "#ERROR# :关闭数据库连接发生异常,请检查!", e);
throw new RuntimeException(e);
}
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.configuration.JAXPConfigurator;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.List;
import java.util.Properties;
/**
* 简单的JDBC工具类
*
* @author leizhimin 2009-11-23 17:35:26
*/
public class MyDB {
private static final Log log = LogFactory.getLog(MyDB. class);
private static final boolean useDBPool = true; //是否使用数据库连接池
private static String dburl = null;
private static String user = null;
private static String password = null;
private static Properties props = new Properties();
static {
init();
}
public static void init() {
if (useDBPool) {
try {
JAXPConfigurator.configure( "proxool.xml", false);
// JAXPConfigurator.configure("src/proxool.xml", false);
} catch (ProxoolException e) {
e.printStackTrace();
}
return;
}
try {
// props.load(new FileInputStream("/jdbc.properties"));
props.load(MyDB. class.getResourceAsStream( "/jdbc.properties"));
} catch (IOException e) {
log.error( "#ERROR# :系统加载sysconfig.properties配置文件异常,请检查!", e);
}
dburl = props.getProperty( "jdbc.url");
user = props.getProperty( "jdbc.username").trim();
password = props.getProperty( "jdbc.password").trim();
System.out.println(dburl);
System.out.println(user);
System.out.println(password);
//注册驱动类
try {
Class.forName(props.getProperty( "jdbc.driver"));
} catch (ClassNotFoundException e) {
log.error( "#ERROR# :加载数据库驱动异常,请检查!", e);
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws FileNotFoundException {
for ( int i = 0; i < 5; i++) {
Connection conn = getConnection();
System.out.println(conn == null ? "没连上" : "连上了");
// System.out.println("--------");
// closeConnection(conn);
}
}
/**
* 创建一个数据库连接
*
* @return 一个数据库连接
*/
public static Connection getConnection() {
Connection conn = null;
//根据连接池配置创建数据库连接
if (useDBPool) {
try {
conn = DriverManager.getConnection( "proxool.ds");
} catch (SQLException e) {
log.error( "#ERROR# :无法从数据库连接池获取到数据库连接!");
throw new RuntimeException(e);
}
return conn;
}
//根据JDBC配置创建数据库连接
try {
conn = DriverManager.getConnection(dburl, user, password);
} catch (SQLException e) {
log.error( "#ERROR# :创建数据库连接发生异常,请检查!", e);
throw new RuntimeException(e);
}
return conn;
}
/**
* 在一个数据库连接上执行一个静态SQL语句查询
*
* @param conn 数据库连接
* @param staticSql 静态SQL语句字符串
* @return 返回查询结果集ResultSet对象
*/
public static ResultSet executeQuery(Connection conn, String staticSql) {
ResultSet rs = null;
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
//执行SQL,并获取返回结果
rs = stmt.executeQuery(staticSql);
} catch (SQLException e) {
log.error( "#ERROR# :执行SQL语句出错,请检查!\n" + staticSql, e);
throw new RuntimeException(e);
}
return rs;
}
/**
* 在一个数据库连接上执行一个静态SQL语句
*
* @param conn 数据库连接
* @param staticSql 静态SQL语句字符串
*/
public static void executeSQL(Connection conn, String staticSql) {
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
//执行SQL,并获取返回结果
stmt.execute(staticSql);
} catch (SQLException e) {
log.error( "#ERROR# :执行SQL语句出错,请检查!\n" + staticSql, e);
throw new RuntimeException(e);
}
}
/**
* 在一个数据库连接上执行一批静态SQL语句
*
* @param conn 数据库连接
* @param sqlList 静态SQL语句字符串集合
*/
public static void executeBatchSQL(Connection conn, List<String> sqlList) {
try {
//创建执行SQL的对象
Statement stmt = conn.createStatement();
for (String sql : sqlList) {
stmt.addBatch(sql);
}
//执行SQL,并获取返回结果
stmt.executeBatch();
} catch (SQLException e) {
log.error( "#ERROR# :执行批量SQL语句出错,请检查!", e);
}
}
public static void closeConnection(Connection conn) {
if (conn == null) return;
try {
if (!conn.isClosed()) {
//关闭数据库连接
conn.close();
}
} catch (SQLException e) {
log.error( "#ERROR# :关闭数据库连接发生异常,请检查!", e);
throw new RuntimeException(e);
}
}
}
运行结果:
[INFO] 2010-02-25 13:05:20 [org.logicalcobwebs.proxool.ProxoolFacade] Proxool 0.9.1 (23-Aug-2008 11:10)
连上了
连上了
连上了
连上了
连上了
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ds] Shutting down 'ds' pool immediately [Shutdown Hook]
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ConnectionPool] Waiting until Thu Feb 25 13:05:22 CST 2010 for all connections to become inactive (active count is 5).
[WARN] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ConnectionPool] Shutdown waited for 0 milliseconds for all the connections to become inactive but the active count is still 5. Shutting down anyway.
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.PrototyperController] Stopping Prototyper thread
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.HouseKeeperController] Stopping HouseKeeper thread
Process finished with exit code 0
连上了
连上了
连上了
连上了
连上了
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ds] Shutting down 'ds' pool immediately [Shutdown Hook]
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ConnectionPool] Waiting until Thu Feb 25 13:05:22 CST 2010 for all connections to become inactive (active count is 5).
[WARN] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.ConnectionPool] Shutdown waited for 0 milliseconds for all the connections to become inactive but the active count is still 5. Shutting down anyway.
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.PrototyperController] Stopping Prototyper thread
[INFO] 2010-02-25 13:05:22 [org.logicalcobwebs.proxool.HouseKeeperController] Stopping HouseKeeper thread
Process finished with exit code 0
Proxool提供的配置方式很多,这里进选择最常用的xml方式,另外的方式也很简单,可以参看官方文档:
三、Proxool很扯蛋的问题----找不到配置文件
proxool的配置文件加载做的比较差劲,通过两个类来加载配置文件:
org.logicalcobwebs.proxool.configuration.PropertyConfigurator
org.logicalcobwebs.proxool.configuration.ServletConfigurator
org.logicalcobwebs.proxool.configuration.XMLConfigurator
org.logicalcobwebs.proxool.configuration.JAXPConfigurator
org.logicalcobwebs.proxool.configuration.AvalonConfigurator
这几个类加载配置文件时候,常常会提示找不到配置文件,其原因是proxool在读取CLASSPATH下路径有问题,经常看到一种情况就是,在开发环境IDE环境下面测试通过,在打包后脱离IDE环境独立运行时候就提示找不到配置文件。这里有一个简单的解决方法就是不要使用文件名指定配置文件,而是通过读取CLASSPATH下的配置文件流,形成字节流传递给配置工具类来实现。比如:
public
static
void init() {
//初始化数据库连接配置参数
InputStream in = MyDB. class.getResourceAsStream( "/proxool.xml");
Reader reader = null;
try {
reader = new InputStreamReader(in, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
JAXPConfigurator.configure(reader, false);
} catch (ProxoolException e) {
e.printStackTrace();
}
}
//初始化数据库连接配置参数
InputStream in = MyDB. class.getResourceAsStream( "/proxool.xml");
Reader reader = null;
try {
reader = new InputStreamReader(in, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
JAXPConfigurator.configure(reader, false);
} catch (ProxoolException e) {
e.printStackTrace();
}
}
在初始化Proxool环境的时候,千万不要把第二个验证参数设置为true,否则老提示验证失败,但是配置文件语法什么都没错,这个问题我仅仅发现了,但没找到根本原因,解决办事是只需要将其设置为false就行。
四、使用ProxoolDataSource
ProxoolDataSource提供了一个java.sql.DataSource接口的简单实现,不过需要一个个的设置属性,比较麻烦,大致思路如下:
public
class TestProxoolDS {
private static ProxoolDataSource ds = null;
public void init(){
ds = new ProxoolDataSource();
ds.setDriver( "com.mysql.jdbc.Driver");
ds.setDriverUrl( "jdbc:mysql://192.168.104.191:3306/cdn");
ds.setUser("vcom");
ds.setPassword("vcom");
ds.setAlias("ds");
ds.setMaximumConnectionCount(5);
ds.setMinimumConnectionCount(0);
ds.setMaximumActiveTime(5);
//todo:继续设置属性,直到没有空指针异常为止
}
public static void main(String argsp[]) throws SQLException {
Connection conn = ds.getConnection();
System.out.println(conn == null ? "没连上" : "连上了"); }
}
private static ProxoolDataSource ds = null;
public void init(){
ds = new ProxoolDataSource();
ds.setDriver( "com.mysql.jdbc.Driver");
ds.setDriverUrl( "jdbc:mysql://192.168.104.191:3306/cdn");
ds.setUser("vcom");
ds.setPassword("vcom");
ds.setAlias("ds");
ds.setMaximumConnectionCount(5);
ds.setMinimumConnectionCount(0);
ds.setMaximumActiveTime(5);
//todo:继续设置属性,直到没有空指针异常为止
}
public static void main(String argsp[]) throws SQLException {
Connection conn = ds.getConnection();
System.out.println(conn == null ? "没连上" : "连上了"); }
}
本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/278521,如需转载请自行联系原作者