数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
连接池的基本概念
························································································邪恶的代码分界线···································································································
源码地址:https://github.com/java-rookie-233333/ConnectionPool
首先我们自己先定义一个SuperDataSource类去实现javax.sql.DataSource和
然后我们在定义一个DatabaseConfiguration类,这个类是用来保存数据库连接池的一些设置信息,这个是我在获取数据库连接时候需要用到的信息
这里的信息是在SuperDataSource进行了一个初始化设置
在这里我进行了数据库的信息保存,然后设置到SuperPool中;
SuperDataSource类代码
package com;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;
import com.pool.SuperPool;
import com.pool.SuperPoolConnection;
import com.uitl.StringUtils;
/**
*
*
* Copyright: Copyright (c) 2017
*
*
* Company: 熠道大数据
*
*
* @ClassName: SuperConnectionPool
* @Description: TODO(数据库连接池)
* @author liuhonbin
* @date 2018年4月24日
*/
public class SuperDataSource extends ResourceManagement implements DataSource,ConnectionPoolDataSource {
protected volatile String username;
protected volatile String password;
protected volatile String jdbcUrl;
protected volatile String driverClass;
protected volatile int initialSize = 0;
protected volatile int minIdle = 0;
protected volatile int maxIdle = 0;
protected volatile int maxActive = 0;
protected volatile long maxWait = 0;
protected volatile long waitTime = 1000L;
private SuperPool superPool = SuperPool.getInstance();
public SuperDataSource() {
}
public SuperDataSource(String username, String password, String jdbcUrl) {
super();
this.username = username;
this.password = password;
this.jdbcUrl = jdbcUrl;
}
public SuperPoolConnection getSuperPoolConnection() {
init();
try {
return superPool.getSuperPoolConnection(getWaitTime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public Connection getConnection() throws SQLException {
SuperPoolConnection superPoolConnection = getSuperPoolConnection();
if(superPoolConnection!=null) {
return superPoolConnection;
}else {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
}
public Connection getConnection(String username, String password) throws SQLException {
if (this.username == null && this.password == null && username != null && password != null) {
this.username = username;
this.password = password;
return getConnection();
}
if (!StringUtils.equals(username, this.username)) {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
if (!StringUtils.equals(password, this.password)) {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
return getConnection();
}
private void init() {
if(superPool.getConfiguration() == null) {
DatabaseConfiguration configuration = new DatabaseConfiguration();
configuration.setDriverClass(getDriverClass());
configuration.setJdbcUrl(getJdbcUrl());
configuration.setUsername(getUsername());
configuration.setPassword(getPassword());
configuration.setInitialSize(getInitialSize());
configuration.setMaxActive(getMaxActive());
configuration.setMaxIdle(getMaxIdle());
configuration.setMaxWait(getMaxWait());
configuration.setMinIdle(getMinIdle());
superPool.setConfiguration(configuration);
}
}
public PooledConnection getPooledConnection() throws SQLException {
SuperPoolConnection superPoolConnection = getSuperPoolConnection();
if(superPoolConnection!=null) {
return superPoolConnection;
}else {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
}
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
if (this.username == null && this.password == null && username != null && password != null) {
this.username = username;
this.password = password;
return getPooledConnection();
}
if (!StringUtils.equals(username, this.username)) {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
if (!StringUtils.equals(password, this.password)) {
throw new UnsupportedOperationException("Not supported by SuperDataSource");
}
return getPooledConnection();
}
//关闭连接池的时候这里要去进行连接集合的清理,目前未做实现
public void close() throws SQLException {
// TODO Auto-generated method stub
}
//****************参数get,set方法分界线******************************************
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;
}
public String getJdbcUrl() {
return jdbcUrl;
}
public void setJdbcUrl(String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
public String getDriverClass() {
return driverClass;
}
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public long getWaitTime() {
return waitTime;
}
public void setWaitTime(long waitTime) {
this.waitTime = waitTime;
}
}
然后定义一个SuperPool类,以下是该类方法属性预览图
SuperPool(这是一个单列模式的类,只会加载一次)
1.initDriver():初始化加载驱动,加载一次后就不会再进行加载
2.getConnection() 获取连接
3.getSuperPoolConnection(long waitTime)获取可用连接(具体实现思路在代码中进行补充)
package com.pool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;
import com.DatabaseConfiguration;
public class SuperPool {
// 在SuperDataSource.getSuperPoolConnection() 方法中进初始化设置
private DatabaseConfiguration configuration;
// 已使用连接
private ArrayBlockingQueue use = new ArrayBlockingQueue(1024);
// 未使用连接
private ArrayBlockingQueue duse = new ArrayBlockingQueue(1024);
// 驱动是否初始化标志位
private boolean initDriver = false;
private SuperPool() {
}
// 初始化驱动方法,只会加载一次
private void initDriver() {
try {
Class.forName(configuration.getDriverClass());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 初始化成功设置为true
initDriver = true;
}
private SuperPoolConnection getConnection() {
// 判断驱动是否初始化加载
if (!initDriver) {
initDriver();
}
Connection conn = null;
// 自定义的一个Connection类,实现了javax.sql.PooledConnection, java.sql.Connection 接口
SuperPoolConnection superPoolConnection = null;
try {
conn = DriverManager.getConnection(configuration.getJdbcUrl(), configuration.getUsername(),
configuration.getPassword());
// 将获取到的连接设置到自定义的Connection实现类中
superPoolConnection = new SuperPoolConnection(conn);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return superPoolConnection;
}
// 单列模式加载
private static class Singteton {
private static SuperPool superPool;
static {
superPool = new SuperPool();
}
public static SuperPool getInstance() {
return superPool;
}
}
public static SuperPool getInstance() {
return Singteton.getInstance();
}
public DatabaseConfiguration getConfiguration() {
return configuration;
}
public void setConfiguration(DatabaseConfiguration configuration) {
this.configuration = configuration;
}
// 获取连接
public SuperPoolConnection getSuperPoolConnection(long waitTime) throws InterruptedException {
SuperPoolConnection superPoolConnection = null;
while (true) {
// 如果可用连接和已用连接加起来的数量小于最大连接,才允许去获取连接,否则设置时间挂起
if (use.size() + duse.size() <= getConfiguration().getMaxIdle()) {
// 如果可用连接小于等于0那就新获取一个连接,返回之前把这个连接放到已用集合中去
if (duse.size() <= 0) {
superPoolConnection = getConnection();
use.put(superPoolConnection);
return superPoolConnection;
} else {
return duse.take();
}
} else {
wait(waitTime);
}
}
}
// 增加一个连接到已用连接集合中去
public void addUse(SuperPoolConnection use) {
this.use.add(use);
}
// 移除一个已用连接
public void removeUse(SuperPoolConnection use) {
this.use.remove(use);
}
// 增加一个可用连接
public void addDuse(SuperPoolConnection duse) {
this.duse.add(duse);
}
// 移除一个可用连接
public void removeDuse(SuperPoolConnection duse) {
this.duse.remove(duse);
}
}
SuperPoolConnection类,实现了javax.sql.PooledConnection, java.sql.Connection接口,在这个类中进行了连接的回收
package com.pool;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.sql.ConnectionEventListener;
import javax.sql.StatementEventListener;
public class SuperPoolConnection implements javax.sql.PooledConnection, java.sql.Connection {
protected Connection connection;
//这个类为单列,在此处不会重复加载,还是原来的第一次加载的对象
private SuperPool superPool = SuperPool.getInstance();
//连接是否关闭标志位
boolean isClosed = false;
//在类初始化的时候要求传入一个java.sql.Connection,这是在SuperPool.getConnection() 中进行了set
public SuperPoolConnection(Connection connection) {
this.connection = connection;
}
//这里去判断接口否关闭的方法进行了自定义的转态控制
public boolean isClosed() throws SQLException {
return isClosed;
}
//关闭此连接时会进行连接回收操作
public void close() throws SQLException {
//将当前对象在已用连接集合中进行移除
superPool.removeUse(this);
//然后在将当前对象加到可用连接集合中
superPool.addDuse(this);
//次连接的转态Close转态设置为true
isClosed = true;
//再将连接设置为null
connection = null;
}
public T unwrap(Class iface) throws SQLException {
return connection.unwrap(iface);
}
public boolean isWrapperFor(Class> iface) throws SQLException {
// TODO Auto-generated method stub
return connection.isWrapperFor(iface);
}
public Statement createStatement() throws SQLException {
// TODO Auto-generated method stub
return connection.createStatement();
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
// TODO Auto-generated method stub
return connection.prepareStatement(sql);
}
public CallableStatement prepareCall(String sql) throws SQLException {
return connection.prepareCall(sql);
}
public String nativeSQL(String sql) throws SQLException {
return connection.nativeSQL(sql);
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
connection.setAutoCommit(autoCommit);
}
public boolean getAutoCommit() throws SQLException {
return connection.getAutoCommit();
}
public void commit() throws SQLException {
connection.commit();
}
public void rollback() throws SQLException {
connection.rollback();
}
public DatabaseMetaData getMetaData() throws SQLException {
// TODO Auto-generated method stub
return connection.getMetaData();
}
public void setReadOnly(boolean readOnly) throws SQLException {
connection.setReadOnly(readOnly);
}
public boolean isReadOnly() throws SQLException {
return connection.isReadOnly();
}
public void setCatalog(String catalog) throws SQLException {
connection.setCatalog(catalog);
}
public String getCatalog() throws SQLException {
return connection.getCatalog();
}
public void setTransactionIsolation(int level) throws SQLException {
connection.setTransactionIsolation(level);
}
public int getTransactionIsolation() throws SQLException {
return connection.getTransactionIsolation();
}
public SQLWarning getWarnings() throws SQLException {
return connection.getWarnings();
}
public void clearWarnings() throws SQLException {
connection.clearWarnings();
}
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
}
public Map> getTypeMap() throws SQLException {
return connection.getTypeMap();
}
public void setTypeMap(Map> map) throws SQLException {
connection.setTypeMap(map);
}
public void setHoldability(int holdability) throws SQLException {
connection.setHoldability(holdability);
}
public int getHoldability() throws SQLException {
return connection.getHoldability();
}
public Savepoint setSavepoint() throws SQLException {
return connection.setSavepoint();
}
public Savepoint setSavepoint(String name) throws SQLException {
return connection.setSavepoint(name);
}
public void rollback(Savepoint savepoint) throws SQLException {
connection.rollback(savepoint);
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
connection.releaseSavepoint(savepoint);
}
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return connection.prepareStatement(sql, autoGeneratedKeys);
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return connection.prepareStatement(sql, columnIndexes);
}
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return connection.prepareStatement(sql, columnNames);
}
public Clob createClob() throws SQLException {
return connection.createClob();
}
public Blob createBlob() throws SQLException {
return connection.createBlob();
}
public NClob createNClob() throws SQLException {
return connection.createNClob();
}
public SQLXML createSQLXML() throws SQLException {
return connection.createSQLXML();
}
public boolean isValid(int timeout) throws SQLException {
return connection.isValid(timeout);
}
public void setClientInfo(String name, String value) throws SQLClientInfoException {
connection.setClientInfo(name, value);
}
public void setClientInfo(Properties properties) throws SQLClientInfoException {
connection.setClientInfo(properties);
}
public String getClientInfo(String name) throws SQLException {
return connection.getClientInfo(name);
}
public Properties getClientInfo() throws SQLException {
return connection.getClientInfo();
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return connection.createArrayOf(typeName, elements);
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return connection.createStruct(typeName, attributes);
}
public void setSchema(String schema) throws SQLException {
connection.setSchema(schema);
}
public String getSchema() throws SQLException {
return connection.getSchema();
}
public void abort(Executor executor) throws SQLException {
connection.abort(executor);
}
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
connection.setNetworkTimeout(executor, milliseconds);
}
public int getNetworkTimeout() throws SQLException {
return connection.getHoldability();
}
public Connection getConnection() throws SQLException {
return connection;
}
public void addConnectionEventListener(ConnectionEventListener listener) {
// TODO Auto-generated method stub
}
public void removeConnectionEventListener(ConnectionEventListener listener) {
// TODO Auto-generated method stub
}
public void addStatementEventListener(StatementEventListener listener) {
// TODO Auto-generated method stub
}
public void removeStatementEventListener(StatementEventListener listener) {
// TODO Auto-generated method stub
}
}
代码测试1
这里我们会发现第一次获取连接如果使用完后进行了关闭,第二次进行获取的时候,获取的是同一个连接对象
测试代码2
如果我们第一次获取连接为进行关闭,那么第二次进行连接获取就是新获取一个连接
如果您觉得我的文章还可以,可以给个好评喲,手动滑稽表情