1. 自定义连接池
需求:预先创建一组连接,用的时候每次取出一个; 用完后,放回。
核心:单例模式、动态代理(可以监测接口中方法的执行)
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;
public class MyPOOL {
private int init = 3;// 初始连接数
private int max = 6;// 最大连接数
private int curr = 0;// 当前连接数
private LinkedList<Connection> connPool = new LinkedList<Connection>();// 存放连接的集合
private String driver;
private String url;
private String username;
private String password;
private static MyPOOL pool = new MyPOOL();
public static MyPOOL getInstance() {// 单例模式
return pool;
}
private MyPOOL() {// 初始化连接
try {
Properties pro = new Properties();
InputStream stream = MyPOOL.class.getClassLoader().getResourceAsStream("db.properties");
pro.load(stream);
driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
} catch (Exception e) {
throw new RuntimeException(e);
}
for (int i = 0; i < init; i++) {
connPool.addLast(createConnection());// 连接加入连接池
curr++;// 记录当前连接数
}
}
private Connection createConnection() {
try {// 创建连接
Class.forName(driver);
final Connection con = DriverManager.getConnection(url, username, password);
// 对con创建其代理对象
Connection proxyCon = (Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), // 类加载器
new Class[] { Connection.class }, // 目标对象实现的接口
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
String methodName = method.getName();
if ("close".equals(methodName)) {
connPool.addLast(con);
} else {
result = method.invoke(con, args);
}
return result;
}
});
return proxyCon;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Connection getConnection() {// 获取连接
if (connPool.size() > 0) {// 判断连接池中是否有连接,如果有就直接从连接池中取
return connPool.removeFirst();
} else if (curr < max) {// 没有并且未达到最大连接数,创建
curr++;// 记录当前使用的连接数
return createConnection();
}
throw new RuntimeException("当前连接已经达到最大连接数目!");// 达到则抛异常
}
public void release(Connection con) {// 释放连接
if (connPool.size() < init) {// 当连接池的数目小于当前连接数,就放入池中
connPool.addLast(con);
} else {
try {// 否则关闭
con.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
MyPOOL p = MyPOOL.getInstance();
Connection connection = p.getConnection();
p.release(connection);
}
}
2. DBCP连接池(核心类:BasicDataSource)
DBCP 是Apache软件基金组织下的开源连接池实现。使用前应导入两个 jar 包(commons-dbcp、commons-pool)。Tomcat 的连接池正是采用DBCP来实现的。
2.1 硬编码方式实现连接池
BasicDataSource source = new BasicDataSource();
//连接池参数配置
source.setUrl("jdbc:oracle:thin:@localhost:1521:orcl"); // 数据库连接字符串
source.setDriverClassName("oracle.jdbc.driver.OracleDriver"); // 数据库驱动
source.setUsername("sys as sysdba"); // 数据库连接用户
source.setPassword("oracle"); // 数据库连接密码
source.setInitialSize(3); // 初始化连接
source.setMaxActive(6); // 最大连接
source.setMaxIdle(3000); // 最大空闲时间
Connection con = source.getConnection();// 获取连接
con.close();// 关闭连接
2.2 配置方式实现连接池
db.properties:
url=jdbc:oracle:thin:@localhost:1521:orcl
driverClassName=oracle.jdbc.driver.OracleDriver
username=sys as sysdba
password=oracle
initialSize=3
maxActive=6
maxIdle=3000
Properties prop = new Properties();// 加载prop配置文件
InputStream inStream = DBCP.class.getClassLoader().getResourceAsStream("db.properties");// 获取文件流
prop.load(inStream);// 加载属性配置文件
DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);// 根据prop配置,直接创建数据源对象
Connection con = dataSouce.getConnection();// 获取连接
con.close();// 关闭
3. C3P0连接池(核心类:ComboPooledDataSource)
最常用的连接池技术,Spring框架,默认支持C3P0连接池技术。
3.1 硬编码方式实现连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数
dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUser("sys as sysdba");
dataSource.setPassword("oracle");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);
Connection con = dataSource.getConnection();//获取连接
con.close();// 关闭
3.2 XML方式实现连接池
c3p0-config.xml:
<c3p0-config>
<default-config><!-- 默认配置 -->
<ptoperty name="driverClass">oracle.jdbc.driver.OracleDriver</ptoperty>
<ptoperty name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:orcl</ptoperty>
<ptoperty name="user">sys as sysdba</ptoperty>
<ptoperty name="password">oracle</ptoperty>
<ptoperty name="initialPoolSize">3</ptoperty>
<ptoperty name="maxPoolSize">6</ptoperty>
<ptoperty name="maxIdleTime">1000</ptoperty>
</default-config>
<name-config name="july">
<ptoperty name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:orcl</ptoperty>
<ptoperty name="driverClass">oracle.jdbc.driver.OracleDriver</ptoperty>
<ptoperty name="user">sys as sysdba</ptoperty>
<ptoperty name="password">oracle</ptoperty>
<ptoperty name="initialPoolSize">3</ptoperty>
<ptoperty name="maxPoolSize">6</ptoperty>
<ptoperty name="maxIdleTime">1000</ptoperty>
</name-config>
</c3p0-config>
// 创建c3p0连接池核心工具类
// 自动加载src下c3p0的配置文件c3p0-config.xml
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置(default-config)
//ComboPooledDataSource dataSource = new ComboPooledDataSource("july");// 使用指定的的配置(name-config)
Connection con = dataSource.getConnection();// 获取连接
con.close();// 关闭