Proxool是一种Java数据库连接池技术。是sourceforge下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。虽说Proxool已经很多年没更新了,但是现在使用Proxool的项目还是非常多的,可见Proxool非常优秀。
Proxool下载:http://proxool.sourceforge.net(能不能打开看你运气了,反正我是没打开)
1.在resource目录新建一个proxool.xml文件,内容为:
<?xml version="1.0" encoding="UTF-8"?> <something-else-entirely> <proxool> <alias>mysql</alias> <!-- 数据源的别名 --> <driver-url>jdbc:mysql://192.168.0.14:3306/test</driver-url> <!-- url连接串 --> <driver-class>com.mysql.jdbc.Driver</driver-class> <!-- 驱动类 --> <driver-properties> <property name="user" value="xxx"/> <!-- 用户名 --> <property name="password" value="xxx"/> <!-- 密码 --> </driver-properties> <!-- 最大连接数(默认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>90000</house-keeping-sleep-time> <!-- 没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受 --> <maximum-new-connections>10</maximum-new-connections> <!-- 最少保持的空闲连接数(默认2个) --> <prototype-count>5</prototype-count> <!-- 在使用之前测试 --> <test-before-use>true</test-before-use> <!-- 用于保持连接的测试语句 --> <house-keeping-test-sql>select * from USER</house-keeping-test-sql> </proxool> </something-else-entirely>
2.还是使用我们之前的例子 ,在TestDAO接口和TestDAOImpl实现中添加getUsrInfoWithProxool方法,通过Proxool连接来获取用户信息,TestDAOImpl代码:
package com.test.jdbc.dao.impl; import java.beans.PropertyVetoException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.logicalcobwebs.proxool.CompositeConnectionListener; import org.logicalcobwebs.proxool.ProxoolException; import org.logicalcobwebs.proxool.ProxoolFacade; import org.logicalcobwebs.proxool.configuration.JAXPConfigurator; import com.mchange.v2.c3p0.ComboPooledDataSource; import com.test.jdbc.dao.TestDAO; public class TestDAOImpl implements TestDAO { String driver="com.mysql.jdbc.Driver"; String c3p0JdbcUrl="jdbc:mysql://192.168.0.14:3306/test"; String user="moster"; String passwd="shzygjrmdwg"; Connection conn=null; /** * c3p0实现 */ public void getUsrInfoWithC3P0(Integer usrId) { ComboPooledDataSource cpds=new ComboPooledDataSource(); String sql="SELECT * FROM USER u WHERE u.USR_ID=" + usrId; try { cpds.setDriverClass(driver); cpds.setJdbcUrl(c3p0JdbcUrl); cpds.setUser(user); cpds.setPassword(passwd); cpds.setMinPoolSize(5); cpds.setAcquireIncrement(5); cpds.setMaxPoolSize(20); conn=cpds.getConnection(); Statement st=conn.createStatement(); ResultSet result=st.executeQuery(sql); while(result.next()) { System.out.println("c3p0:begin"); System.out.println("Name:" + result.getString("NAME")); System.out.println("c3p0:end"); } result.close(); st.close(); conn.close(); } catch(PropertyVetoException e) { e.printStackTrace(); } catch(SQLException e) { e.printStackTrace(); } } /** * Proxool实现 * @throws ProxoolException */ public void getUsrInfoWithProxool(Integer usrId) { String sql="SELECT * FROM USER u WHERE u.USR_ID=" + usrId; try { //PropertyConfigurator.configure("resource/proxool.properties"); JAXPConfigurator.configure("resource/proxool.xml", false); ProxoolFacade.addConnectionListener("mysql", new CompositeConnectionListener()); Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); conn = DriverManager.getConnection("proxool.mysql"); Statement st=conn.createStatement(); ResultSet result=st.executeQuery(sql); while(result.next()) { System.out.println("Proxool:begin"); System.out.println("Name:" + result.getString("NAME")); System.out.println("Proxool:end"); } } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(SQLException e) { e.printStackTrace(); } catch(ProxoolException e) { e.printStackTrace(); } } }
3.在main函数中添加调用Proxool的方法进行测试,会显示以下结果:
c3p0:begin Name:g21121 c3p0:end Proxool:begin Name:g21121 Proxool:end
上述也可以采用属性文件,加载方法类似。如果是web项目亦可在web.xml中配置:
<!-- 加载proxool配置文件 --> <servlet> <servlet-name>ServletConfigurator</servlet-name> <servlet-class> org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF\classes\proxool.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
Proxool监控功能:
Proxool提供了一个非常实用的功能——监控,通过这个实用的功能我们可以很轻松的观察连接池的状态机变化并作出应对,实现Proxool的监控功能,我们需要对项目进行一些改造:
1.需要将原项目转换成web项目,这里可以新建或者利用eclipse插件直接转换。
2.在修改web.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 加载proxool配置文件 --> <servlet> <servlet-name>ServletConfigurator</servlet-name> <servlet-class> org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF\classes\proxool.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- proxool监控servlet --> <servlet> <servlet-name>proxool</servlet-name> <servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>proxool</servlet-name> <url-pattern>/admin</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
好了非常简单,打开浏览器输入http://你的服务地址/admin 就行了。
下面是Proxool的参数配置及意义:
#它是一个逗号分割的信息片段当一个SQL异常发生时,他的异常信息将与这个信息片段进行比较如果在片段中存在,那么这个异常将被认为是个致命错误 (Fatal SQL Exception )这种情况下,数据库连接将要被放弃无论发生什么,这个异常将会被重掷以提供给消费者用户最好自己配置一个不同的异常来抛出 fatal-sql-exception=null #正如上面所说,你最好配置一个不同的异常来重掷利用这个属性,用户可以包装SQLException,使他变成另外一个异常这个异常或者继承SQLException或者继承字RuntimeExceptionproxool fatal-sql-exception-wrapper-class=null #house keeper 保留线程处于睡眠状态的最长时间,house keeper 的职责就是检查各个连接的状态,并判断是否需要销毁或者创建,单位:秒,默认:30 house-keeping-sleep-time=30 #如果发现了空闲的数据库连接house keeper 将会用这个语句来测试这个语句最好非常快的被执行如果没有定义,测试过程将会被忽略。 house-keeping-test-sql=select * from test where id=1 #允许proxool实现被代理的connection injectable-connection-interface=null #允许proxool实现被代理的Statement injectable-statement-interface=null #允许proxool实现被代理的PreparedStatement injectable-prepared-statement-interface=null #允许proxool实现被代理的CallableStatement injectable-callable-statement-interface=null #如果属性为true,就会注册一个消息Bean到jms服务,消息Bean对象名="Proxool:type=Pool, name=<alias>" 默认值为false jmx=false #这个属性是仅当"jmx"属性设置为"true"才有效。所有注册jmx服务器使用这个属性是不确定的 jmx-agent-id= #jndi名称 jndi-name=test #如果housekeeper 检测到某个线程的活动时间大于这个数值它将会杀掉这个线程所以确认一下你的服务器的带宽然后定一个合适的值,单位:分钟,默认5 maximum-active-time=5 #最大的数据库连接数 maximum-connection-count=25 #最小的数据库连接数 minimum-connection-count=1 #一个线程的最大寿命,单位:小时,默认:4 maximum-connection-lifetime=4 #这可以帮助我们确定连接池的状态。如果我们已经拒绝了一个连接在这个设定值(毫秒),然后被认为是超载。单位:秒,默认:60 overload-without-refusal-lifetime=60 #连接池中可用的连接数量如果当前的连接池中的连接少于这个数值新的连接将被建立,默认:0 prototype-count=0 #这可以帮助我们确定连接池的状态,连接数少还是多或超载。只要至少有一个连接已开始在此值(毫秒)内,或者有一些多余的可用连接,那么我们假设连接池是开启的。单位:秒,默认:60秒 recently-started-threshold= #这是我们可一次建立的最大连接数。那就是新增的连接请求,但还没有可供使用的连接。由于连接可以使用多线程,在有限的时间之间建立联系从而带来可用连接,但是我们需要通过一些方式确认一些线程并不是立即响应连接请求的,默认:10。 simultaneous-build-throttle=10 #连接池使用状况统计,参数“10s,1m,1d”,默认:null statistics=null #日志统计跟踪类型。参数“ERROR”或 “INFO” statistics-log-level=INFO #如果为true,在每个连接被测试前都会服务这个连接,如果一个连接失败,那么将被丢弃,另一个连接将会被处理,如果所有连接都失败,一个新的连接将会被建立。否则将会抛出一个SQLException异常。 test-before-use= #如果为true,在每个连接被测试后都会服务这个连接,使其回到连接池中,如果连接失败,那么将被废弃。 test-after-use= #如果为true,那么每个被执行的SQL语句将会在执行期被log记录(DEBUG LEVEL)你也可以注册一个ConnectionListener (参看ProxoolFacade)得到这些信息,默认:false trace=false
最后是这个项目的源代码供大家参考,代码比较简单没做任何优化,提供一个思路而已。