数据库连接池需要满足
- javax.sql.DataSource
- 对象池,对象池实际上是java.sql.Connection的缓存池。
实现
- maven依赖
我使用的是org.apache.commons>commons-pool2做的对象池。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
- Java代码
package org.march.dbp.pool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class ConnectionConfig extends GenericObjectPoolConfig {
public ConnectionConfig() {
}
}
package org.march.dbp.pool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.march.dbp.conn.JdbcConfig;
public class ConnectionFactory extends BasePooledObjectFactory<Connection> {
private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
private JdbcConfig jdbcConfig;
private ConnectionPool connectionPool;
public ConnectionFactory(JdbcConfig jdbcConfig, ConnectionPool connectionPool) {
this.jdbcConfig = jdbcConfig;
this.connectionPool = connectionPool;
}
@Override
public Connection create() throws Exception {
Connection connection = DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getPassword(),
jdbcConfig.getPassword());
Connection con = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES,
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("close")) {
connectionPool.returnConn((Connection) proxy);
return null;
} else {
return method.invoke(connection, args);
}
}
});
return con;
}
@Override
public PooledObject<Connection> wrap(Connection obj) {
return new DefaultPooledObject<Connection>(obj);
}
}
package org.march.dbp.pool;
import java.sql.Connection;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.march.dbp.conn.JdbcConfig;
public class ConnectionPool {
private GenericObjectPool<Connection> pool = null;
public static ConnectionPool build(JdbcConfig jdbcConfig) {
return new ConnectionPool(jdbcConfig);
}
private ConnectionPool(JdbcConfig jdbcConfig) {
ConnectionConfig myPoolConfig = new ConnectionConfig();
myPoolConfig.setMaxTotal(5);
pool = new GenericObjectPool<>(new ConnectionFactory(jdbcConfig, this), myPoolConfig);
}
public Connection getConn() {
try {
Connection conn = pool.borrowObject();
return conn;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public void returnConn(Connection conn) {
pool.returnObject(conn);
}
}
package org.march.dbp.conn;
public class JdbcConfig {
private String url;
private String username;
private String password;
public JdbcConfig(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return url + " " + username + " " + password;
}
}
package org.march.dbp.ds;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.march.dbp.conn.JdbcConfig;
import org.march.dbp.pool.ConnectionPool;
public class MarchDataSource implements DataSource {
private PrintWriter out;
private int loginTimeout;
private ConnectionPool connectionPool;
public MarchDataSource(String url, String username, String password) {
connectionPool = ConnectionPool.build(new JdbcConfig(url, username, password));
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return out;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
this.out = out;
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
this.loginTimeout = seconds;
}
@Override
public int getLoginTimeout() throws SQLException {
return loginTimeout;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection() throws SQLException {
return connectionPool.getConn();
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
}
- 测试
public class MarchDataSourceTest extends TestCase {
public MarchDataSourceTest(String testName) {
super(testName);
}
public void testApp() throws SQLException {
MarchDataSource m = new MarchDataSource("jdbc:mysql://127.0.0.1:3306/wang", "root", "root");
Connection con = m.getConnection();
System.out.println(con);
con.close();
}
}
代码在 https://github.com/faicm/march/tree/master/march-dbp。我还会持续修改。