数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,如此一来,对于大量的数据库连接操作就会造成系统性能低下。
为了避免频繁地创建和销毁 JDBC 连接,我们可以通过连接池(Connection Pool)复用已经创建好的连接。
JDBC 连接池有一个标准的接口:javax.sql.DataSource,这个类位于 Java 标准库中,但这仅仅是一个接口。要使用 JDBC 连接池,我们必须选择一个 JDBC 连接池的实现。常用的 JDBC 连接池有:
- HikariCP
- C3P0
- BoneCP
- Druid
本文主要介绍 Druid 连接池。
Druid 连接池是阿里巴巴开源的数据库连接池项目。Druid 连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防 SQL 注入,内置 Loging 能诊断 Hack 应用行为。
- GitHub 地址:https://github.com/alibaba/druid
- jar 包下载地址:https://repo1.maven.org/maven2/com/alibaba/druid/
- 使用文档:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
Maven 工程使用下面这个配置:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.17</version>
</dependency>
Druid 连接池的使用步骤:
- 下载 jar 包或导入依赖
- 定义配置文件
- 加载配置文件
- 获取数据连接池对象:通过工厂来获取 DruidDataSourceFactory
- 获取连接
- 归还连接
jar 包与依赖在此不再赘述,jar 包使用和 JDBC 驱动的 jar 包的使用一致,Maven 依赖对于学过 Maven 的读者来说也不需要解释。
定义配置文件
配置文件是 properties 形式的,需要手动加载,同时该配置文件可以放在任意目录下,但建议放在 src 目录下,Maven 工程放在 resources 目录下。
此处创建一个 druid.properties 配置文件,文件内容如下:
# 连接操作不可缺少的数据
url=jdbc:mysql://localhost:3306/test
username=YourName
password=YourPassword
driverClass=com.mysql.cj.jdbc.Driver
# 其它
initialSize=10 # 初始化连接数量
maxActive=10 # 最大连接数
filters=wall
将该文件放在 resources 下
注意,此处我创建的是 Maven 工程,因此对于非 Maven 工程的项目,目录结构会有所不同。对于非 Maven 工程的项目,建议在 src 下创建一个 resources 目录,将配置文件放在该目录下。
加载配置文件
加载配置文件最容易出错的就是程序无法识别到配置文件所在位置。对于非 Maven 工程的项目,可以打印当前路径获取路径信息,从而让程序找到配置文件所在位置。打印当前路径信息代码如下:
System.out.println(System.getProperty("user.dir"));
对于 Maven 工程或其它工程的项目,找到 resources 目录,将配置文件放在该目录下,然后设定该目录为资源根目录即可。
加载 properties 文件代码如下:
Properties properties = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
获取数据连接池对象
Druid 连接池对象是通过一个工厂类 DruidDataSourceFactory 获取的,通过调用该类的 createDataSource()方法,将加载到的配置文件对象传入进去,即可得到一个连接池对象。代码如下:
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
获取连接
拥有一个连接池对象后,我们就能通过该对象的 getConnection()方法获取数据库连接对象,代码如下:
Connection connection = dataSource.getConnection();
关闭连接
connection.close();
完整代码
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* ClassName: JDBCDruidExample
* Package: PACKAGE_NAME
* Description:
*
* @Author: Ning
* @Create: 2023/4/29 - 22:50
*/
public class JDBCDruidExample {
@Test
public void connectionDruidTest() throws Exception{
// System.out.println(System.getProperty("user.dir"));
// 加载配置文件
Properties properties = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
// 获取数据池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
// 关闭连接
connection.close();
}
}
封装 Druid 数据库连接类
开发中,我们不可能每次需要连接数据库时重新写一遍上述流程。一般的,我们会将上述流程进行封装,封装为一个数据库连接类重复使用。
package Utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* ClassName: DruidConnection
* Package: Utils
* Description:
*
* @Author: Ning
*/
public class DruidConnection {
// 使用Druid数据库连接池技术
private static DataSource source;
static {
try {
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
source = DruidDataSourceFactory.createDataSource(pros);
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getConnetion() throws SQLException{
Connection conn = source.getConnection();
return conn;
}
}
测试
对我们封装好的类进行测试。
import Utils.DruidConnection;
import org.junit.Test;
import java.sql.Connection;
/**
* ClassName: DruidConnectionTest
* Package: PACKAGE_NAME
* Description:
*
* @Author: Ning
*/
public class DruidConnectionTest {
@Test
public void druidConnectionTest() throws Exception{
Connection conn = DruidConnection.getConnetion();
System.out.println(conn);
conn.close();
}
}
运行结果: