Tomcat 7 的新JDBC连接池的使用说明
Tomcat 7 的JDBC连接池实现类为org.apache.tomcat.jdbc.pool,作为替换commons-dbcp的方案。
替换commons-dbcp的原因如下:
commons-dbcp是单线程的,为了线程安全,就要琐住整个连接池,查询验证阶段也要琐住整个连接池。commons-dbcp速度慢,性能差,多CPU的环境下单线程运行,不支持高并发,在JAVA 6中也不能解决速度和并发的问题。commons-dbcp实现复杂,超过60个类。tomcat-jdbc-pool核心只有8个类,修改更加简单,只需运行连接池本身,易测试。commons-dbcp应用静态接口,就意味着并不能用JDK 1.6编译它,在JDK 1.6/1.7中运行时,即使驱动程序支持,所有没有实现的方法也都会抛出NoSuchMethodException异常。commons-dbcp几乎停滞,很少更新。commons-dbcp没有的公平算法,并且比commons-dbcp性能更好。javax.sql.PooledConnection接口获取连接。除了commons-dbcp连接池,还有其它可以选择的方案,如c3p0,bonecp等,与这些连接池实现相比,Tomcat jdbc pool更突出的功能体现在:
java.sql和javax.sql接口,可以使用低版本JDK编译。Future<Connection> ResetAbandonedTimer完成。removeAbandonedTimeout相似,但是只输出信息,不做任何操作。使用suspectTimeout属性完成设置。java.sql.Driver,javax.sql.DataSource或者javax.sql.XADataSource中取得连接,使用dataSource和dataSourceJNDI属性完成。import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import org.apache.tomcat.jdbc.pool.DataSource;import org.apache.tomcat.jdbc.pool.PoolProperties;public class SimplePOJOExample {public static void main(String[] args) throws Exception { PoolProperties p = new PoolProperties(); p.setUrl("jdbc:mysql://localhost:3306/mysql"); p.setDriverClassName("com.mysql.jdbc.Driver"); p.setUsername("root"); p.setPassword("password"); p.setJmxEnabled(true); p.setTestWhileIdle(false); p.setTestOnBorrow(true); p.setValidationQuery("SELECT 1"); p.setTestOnReturn(false); p.setValidationInterval(30000); p.setTimeBetweenEvictionRunsMillis(30000); p.setMaxActive(100); p.setInitialSize(10); p.setMaxWait(10000); p.setRemoveAbandonedTimeout(60); p.setMinEvictableIdleTimeMillis(30000); p.setMinIdle(10); p.setLogAbandoned(true); p.setRemoveAbandoned(true); p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); DataSource datasource = new DataSource(); datasource.setPoolProperties(p); Connection con = null; try { con = datasource.getConnection(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery("select * from user"); int cnt = 1; while (rs.next()) { System.out.println((cnt++)+". Host:" +rs.getString("Host")+ " User:"+rs.getString("User")+" Password:"+rs.getString("Password")); } rs.close(); st.close(); } finally { if (con!=null) try {con.close();}catch (Exception ignore) {} } }}??作为数据源在Tomcat中使用<resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" testwhileidle="true" testonborrow="true" testonreturn="false" validationquery="SELECT 1" validationinterval="30000" timebetweenevictionrunsmillis="30000" maxactive="100" minidle="10" maxwait="10000" initialsize="10" removeabandonedtimeout="60" removeabandoned="true" logabandoned="true" minevictableidletimemillis="30000" jmxenabled="true" jdbcinterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer" username="root" password="password" driverclassname="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mysql"> 2 </resource>
?异步获取连接1.必须将fairQueue设置为true
2.必须将数据源转换为org.apache.tomcat.jdbc.pool.DataSource
Connection con = null; try { Future future = datasource.getConnectionAsync(); while (!future.isDone()) { System.out.println("Connection is not yet available. Do some background work"); try { Thread.sleep(100); //simulate work }catch (InterruptedException x) { Thread.currentThread().interrupted(); } } con = future.get(); //should return instantly Statement st = con.createStatement(); ResultSet rs = st.executeQuery("select * from user");
??
?