1:先是配置文件:
<?xml version="1.0" encoding="gb2312"?> <!-- the proxool configuration can be embedded within your own application's. Anything outside the "proxool" tag is ignored. --> <something-else-entirely> <proxool> <alias>example</alias> <driver-url> jdbc:oracle:thin:@*.*.*.*:1521:**** </driver-url> <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <driver-properties> <property name="user" value="*****" /> <property name="password" value="*****" /> </driver-properties> <!--最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 --> <maximum-connection-count>20</maximum-connection-count> <!--最小连接数(默认2个,包含活动的和空闲的)--> <minimum-connection-count>4</minimum-connection-count> <!--proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒--> <house-keeping-sleep-time>30000</house-keeping-sleep-time> <!--没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受--> <!-- maximum-new-connections不被推荐使用了,所以用simultaneous-build-throttle来代替了 --> <simultaneous-build-throttle>15</simultaneous-build-throttle> <!--maximum-new-connections>10</maximum-new-connections--> <!--最少保持的空闲连接数(默认2个)--> <prototype-count>2</prototype-count> <!-- maximum-active-time缺省5minutes 172800000毫秒=48小时--> <maximum-active-time>172800000</maximum-active-time> <!-- maximum-connection-lifetime缺省4hours 180000000毫秒=50小时--> <maximum-connection-lifetime>180000000</maximum-connection-lifetime> <!--在使用之前测试--> <test-before-use>false</test-before-use> <!--用于保持连接的测试语句 --> <!-- house-keeping-test-sql> select sysdate from dual </house-keeping-test-sql --> <!-- 是否监控sql信息 --> <trace>true</trace> <!-- statistics>10s,1m</statistics --> <!-- statistics-log-level>DEBUG</statistics-log-level --> </proxool> </something-else-entirely>
注释:(以上的数据连接IP和用户名密码根据自己的实际情况填写)
配置文件里的两行
<!-- maximum-active-time缺省5minutes 172800000毫秒=48小时-->
<maximum-active-time>172800000</maximum-active-time>
<!-- maximum-connection-lifetime缺省4hours 180000000毫秒=50小时-->
<maximum-connection-lifetime>180000000</maximum-connection-lifetime>
第一个48小时的是设置连接活动的时间,即:你的sql或存储过程执行的时间,估算一下你的应用中的sql或存储过程最长的执行时间a,将这个值设为大于a就行了,这是项目中实际发现的问题经验,我有个sql执行时间超过了5分钟,而原来没有设置这个值,缺省为5分钟,所以我的应用刚起来没问题,跑一段时间,跑到这个sql时执行了一段时间后台就报:
java.sql.SQLException: Couldn't perform the operation prepareStatement: You can't perform any operations on this connection. It has been automatically closed by Proxool for some reason (see logs).
这个错误,后来去官方网页查看Properties发现,如果超过这个值,proxool就会自动kill掉这个连接。
第二个50个小时是设置连接的寿命,这个值理论上应该大于连接的活动时间限制,不然活动时间限制就没有意义了,所以设为了50个小时
2:连接类
package com.ai.dyjf.base;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.logicalcobwebs.proxool.ConnectionInfoIF;
import org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.ProxoolFacade;
import org.logicalcobwebs.proxool.admin.SnapshotIF;
import org.logicalcobwebs.proxool.configuration.JAXPConfigurator;
import org.xml.sax.InputSource;
import com.toolkit.my.db.DBAException;
import com.toolkit.my.db.base.IDBConnectionPool;
public class CCConnectionPoolUtil implements IDBConnectionPool{
private static int activeCount = 0;//当前连接数
static {
try {
JAXPConfigurator.configure(new InputSource(CCConnectionPoolUtil.class.getResourceAsStream("proxoolCC.xml")),
false);
} catch (ProxoolException e) {
System.out
.println("没有找到proxool的配置文件,请查看/src/com/ai/dyjf/base/proxoolCC.xml是否存在!");
e.printStackTrace();
}
}
/**
* 测试用的获取数据库连接
* @return
*/
public Connection getConnectionFromPool() {
Connection conn = null;
// // 1:注册驱动类,这次这个驱动已经不是Oracle的驱动了,是Proxool专用的驱动
// try {
// Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
// // 2:创建数据库连接,这个参数是一个字符串,是数据源的别名,在配置文件中配置的timalias,参数格式为:proxool.数据源的别名
// conn = DriverManager.getConnection("proxool.example");
// ConnectionPoolDefinitionIF cpd =ProxoolFacade.getConnectionPoolDefinition("example");
// SnapshotIF snapshotIF=ProxoolFacade.getSnapshot("example", true);
// int curActiveCount = snapshotIF.getActiveConnectionCount();// 获得活动(正在使用的busy)连接数
// if (curActiveCount != activeCount)// 当活动连接数变化时输出信息
// {
// System.out.println("activeCount:"+activeCount);
// FileWriter fw=null;
// SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// int availableCount = snapshotIF.getAvailableConnectionCount();// 获得可得到的(空闲的free)连接数
// int maxCount = snapshotIF.getMaximumConnectionCount();// 获得总连接数(最大的)
// int offlineCount=snapshotIF.getOfflineConnectionCount();//获得不在线的连接数(释放的)
// long refusedCount=snapshotIF.getRefusedCount();//How many connections have been refused since the pool started
// long servedCount=snapshotIF.getServedCount();//How many connections have been served since the pool started
//
//
// Date snapshotDate=snapshotIF.getSnapshotDate();
// ConnectionInfoIF[] connIF=snapshotIF.getConnectionInfos();
// try {
// fw=new FileWriter("proxoolCC.log",true);
// fw.write("\n\n----------------连接数信息------------------\n");
// fw.write("监控时间:"+sdf.format(snapshotDate)+"\n");
// fw.write("busy连接数:"+curActiveCount+"\n");
// fw.write("free连接数:"+availableCount+"\n");
// fw.write("max连接数:"+maxCount+"\n");
// fw.write("offlineCount连接数:"+offlineCount+"\n");
// fw.write("refusedCount连接数:"+refusedCount+"\n");
// fw.write("servedCount连接数:"+servedCount+"\n");
// fw.write("----------------连接信息-----------------\n");
// for(int i=0;i<connIF.length;i++){
// ConnectionInfoIF connInfo=connIF[i];
// fw.write("ConnectionId号:"+connInfo.getId()+"\n");
// fw.write("Connection初始化时间:"+sdf.format(new Date(connInfo.getBirthTime()))+"\n");
// fw.write("Connection年龄(mis):"+connInfo.getAge()+"\n");
// fw.write("Connection状态(active-2;available-1;null-0;offline-3):"+connInfo.getStatus()+"\n");
// fw.write("Connection最后一次活动开始时间:"+sdf.format(new Date(connInfo.getTimeLastStartActive()))+"\n");
// fw.write("Connection最后一次活动结束时间:"+sdf.format(new Date(connInfo.getTimeLastStopActive()))+"\n");
// fw.write("Connection最后一次活动占用时长(mis):"+(connInfo.getTimeLastStopActive()-connInfo.getTimeLastStartActive())+"\n");
// String[] sqlCallsStrs=connInfo.getSqlCalls();
// for(int j=0;i<sqlCallsStrs.length;j++){
// fw.write("---------该连接执行的sql语句----------");
// fw.write(sqlCallsStrs[j]);
// fw.write("-----------------------------------");
// }
//
// }
// activeCount = curActiveCount;
// } catch (IOException e) {
// e.printStackTrace();
// }finally{
// if(null!=fw){
// try {fw.close();} catch (IOException e) {e.printStackTrace();}
// }
// }
System.out.println("----------------------------------");
System.out.println("监控时间:"+new SimpleDateFormat("yyyy-MM-dd HH24:mm:ss").format(snapshotDate));
System.out.println("busy连接数:"+curActiveCount);
System.out.println("free连接数:"+availableCount);
System.out.println("max连接数:"+maxCount);
System.out.println("offlineCount连接数:"+offlineCount);
System.out.println("refusedCount连接数:"+refusedCount);
System.out.println("servedCount连接数:"+servedCount);
System.out.println("trace:"+cpd.isTrace());
System.out.println("trace:"+cpd.getStatisticsLogLevel());
// System.out.println(curActiveCount + "(active) " + availableCount + "(available) " + maxCount + "(max)");
System.out.println("----------------------------------");
activeCount = curActiveCount;
// }
//
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// } catch (SQLException e) {
// e.printStackTrace();
// } catch (ProxoolException e) {
// e.printStackTrace();
// }
return conn;
}
/**
* 关闭数据库连接
* @param conn
*/
public void releaseConnection(Connection conn){
try {
//关闭数据库连接
// Check to see we actually got a connection before we
// attempt to close it.
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() throws DBAException {
}
/**
* 真正业务调用的连接
*/
public Connection fetchConnection() throws DBAException {
Connection conn = null;
// 1:注册驱动类,这次这个驱动已经不是Oracle的驱动了,是Proxool专用的驱动
try {
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
// 2:创建数据库连接,这个参数是一个字符串,是数据源的别名,在配置文件中配置的timalias,参数格式为:proxool.数据源的别名
conn = DriverManager.getConnection("proxool.example");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
注释:
上面getConnectionFromPool() 这个方法是自己测试连接的方法,自己可以根据实际情况查看连接池的状态
另:如果是java应用使用Proxool则需要自己写 单例连接池获取类 实现,并保证连 该获取类的生命周期不销毁,
比如可以写监听类(用死循环实现),或是用定时任务TimeTask实现定时类,在定时类里去连接。总之就是要保证这个java应用的main不会结束,要保证连接池类的生命周期不被销毁并保持单例.
下面是个简单的提示类:
public class SysUtil {
private IDBConnectionPool dbConnectionPool;
private IConfigReader configReader;
private ILogger logger;
private int maxLogLevel = 0;
private boolean systemOut = false;
private static SysUtil _inst = null;
static public SysUtil instance(){
if(_inst == null){
_inst = new SysUtil();
}
return _inst;
}
private SysUtil(){
init();
}
private void init(){
try{
configReader = new PropertiesConfig("config.txt");
// dbConnectionPool = new NoConnectionPool(configReader.getValue("DBDirver"),configReader.getValue("DBUrl")
// ,configReader.getValue("DBUser"),configReader.getValue("DBPass"));
// 修改了通过连接池的实现
dbConnectionPool=new CCConnectionPoolUtil();
logger = new DBTableLogger(dbConnectionPool);
((ChainLogger)logger).setNextLogger(new Log4jLogger("log4j.properties",""));
// 这里传true才能正确解释,传false感觉没道理
((ChainLogger)logger).setOnlyOnError(true);
maxLogLevel = Integer.parseInt(configReader.getValue("MaxLogLevel"));
systemOut = configReader.getValue("SYSTEMOUT").toUpperCase()=="TRUE"?true:false;
}catch(ConfigException ce){
ce.printStackTrace();
throw new RuntimeException("SysUtil初始化失败!"+ce.getMessage(),ce);
}
}
public String getConfigValue(String key) throws ConfigException{
return configReader.getValue(key);
}
public Connection fetchConnection() throws DBAException{
return dbConnectionPool.fetchConnection();
}
public void releaseConnection(Connection connection) throws DBAException{
dbConnectionPool.releaseConnection(connection);
}
}
只看上面类的部分代码,这个类就是用来从 CCConnectionPoolUtil 类里去连接的单例工具类
然后你可以在你的TimerTask里用这个工具类来取数据库连接实现逻辑,或这是你的不会结束的main里调用这个工具类来取数据库连接. 例如main里调用task的start,或是mian里用for(;;){这里分线程去做业务逻辑;}
如果是在web应用中使用Proxool则网上有很多怎么和web.xml或是spring配置结合的例子,这里就不在概述了!