/**
* 连接池
*/
public class ConnectionPool implements DataSource {
// 连接配置
/** 驱动类 */
private String driver;
/** 数据库地址 */
private String url;
/** 账号 */
private String username;
/** 密码 */
private String password;
// 连接池配置
/** 最大活跃连接数 */
private int maxActive;
/** 最大空闲连接数*/
private int maxIdle;
/** 活跃连接 */
private List<PooledConnection> activeConnections = new ArrayList<>();
/** 空闲连接 */
private List<PooledConnection> idleConnections = new ArrayList<>();
private final Object lock = new Object();
/** 所有JDBC驱动 */
private static Map<String, Driver> driverMap = new ConcurrentHashMap<>();
static {
Enumeration<Driver> driverEnumeration = DriverManager.getDrivers();
while (driverEnumeration.hasMoreElements()) {
Driver driver = driverEnumeration.nextElement();
driverMap.put(driver.getClass().getCanonicalName(), driver);
}
}
public ConnectionPool(String driver, String url, String username, String password, int maxActive, int maxIdle) {
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
this.maxActive = maxActive;
this.maxIdle = maxIdle;
}
/**
* 借出连接
*/
private Connection borrowConnection(String username, String password) throws SQLException {
PooledConnection connection = null;
while (connection == null) {
synchronized (lock) {
if (idleConnections.size() > 0) {
// 有空闲连接
connection = idleConnections.remove(0);
} else {
if (activeConnections.size() < maxActive) {
// 未达到最大活跃连接数,则生成一个新连接
Connection realConnection = doGetConnection(username, password);
connection = new PooledConnection(realConnection, this);
} else {
// 已达到最大数量,等待
try {
lock.wait();
} catch (InterruptedException e) {
break;
}
}
}
if (connection != null) {
// 借出时检查
if (connection.isValid()) {
activeConnections.add(connection);
} else {
connection.invalidate();
connection.getRealConnection().close();
connection = null;
}
}
}
}
if (connection == null) {
throw new SQLException("The connection pool returned a null connection");
}
// 返回代理对象
return connection.getProxyConnection();
}
/**
* 生成一个真正的连接
*/
private Connection doGetConnection(String username, String password) throws SQLException {
initializerDriver();
Connection connection = DriverManager.getConnection(url, username, password);
// 配置连接
return connection;
}
/**
* 初始化数据库驱动
*/
private synchronized void initializerDriver() throws SQLException {
if (!driverMap.containsKey(driver)) {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new SQLException("Error setting driver " + driver + " : " + e);
}
}
}
/**
* 归还连接
*/
void returnConnection(PooledConnection connection) throws SQLException {
synchronized (lock) {
// 从活跃连接集合去掉
activeConnections.remove(connection);
// 归还时检查
if (connection.isValid()) {
if (idleConnections.size() < maxIdle) {
// 未达到最大空闲连接数,归还池中
idleConnections.add(connection);
// 通知等待连接的线程
lock.notifyAll();
} else {
// 关闭连接
connection.invalidate();
connection.getRealConnection().close();
}
}
}
}
/**
* 检查连接
*/
boolean pingConnection(Connection connection) {
if (connection == null) {
return false;
}
try {
if (connection.isClosed()) {
return false;
}
} catch (SQLException e) {
e.printStackTrace();
return false;
}
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT 1");
resultSet.close();
statement.close();
return true;
} catch (Exception e) {
e.printStackTrace();
try {
connection.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
return false;
}
}
/**
* 关闭连接池
*/
void closeAll() {
Consumer<List<PooledConnection>> closePool = (pool) -> {
if (pool != null) {
Iterator<PooledConnection> iterator = pool.iterator();
while (iterator.hasNext()) {
PooledConnection pooledConnection = iterator.next();
iterator.remove();
pooledConnection.invalidate();
Connection realConnection = pooledConnection.getRealConnection();
try {
realConnection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
};
synchronized (lock) {
closePool.accept(activeConnections);
closePool.accept(idleConnections);
}
}
@Override
protected void finalize() throws Throwable {
closeAll();
super.finalize();
}
@Override
public Connection getConnection() throws SQLException {
return borrowConnection(this.username, this.password);
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return borrowConnection(username, password);
}
}
/**
* 池化连接,Connection的代理
*/
class PooledConnection implements InvocationHandler {
/** 真实连接 */
private Connection realConnection;
/** 代理连接 */
private Connection proxyConnection;
/** 连接有效状态 */
private boolean valid;
/** 所属连接池 */
private ConnectionPool connectionPool;
PooledConnection(Connection realConnection, ConnectionPool connectionPool) {
this.realConnection = realConnection;
this.connectionPool = connectionPool;
this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
new Class<?>[]{Connection.class}, this);
}
public Connection getRealConnection() {
return realConnection;
}
public Connection getProxyConnection() {
return proxyConnection;
}
/**
* 检查连接是否有效
*/
public boolean isValid() {
return valid && connectionPool.pingConnection(realConnection);
}
/**
* 置为无效
*/
public void invalidate() {
this.valid = false;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("close")) {
// 拦截close方法:关闭连接 -> 返还到连接池
connectionPool.returnConnection(this);
return null;
} else {
return method.invoke(realConnection, args);
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PooledConnection) {
return realConnection.hashCode() == ((PooledConnection) obj).realConnection.hashCode();
} else if (obj instanceof Connection) {
return realConnection.hashCode() == obj.hashCode();
} else {
return false;
}
}
}
网友评论