目录
1.改进后的 JDBCUtils
工具类:
读取src目录下的:jdbc.properties文件:
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
user=root
password=root
driver= com.mysql.jdbc.Driver
package com.work.jdbc;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
try {
// 1. 创建 Properties 对象
Properties pro = new Properties();
// 2. 使用 ClassLoader 加载配置文件
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
try (InputStream input = classLoader.getResourceAsStream("jdbc.properties")) {
if (input == null) {
throw new RuntimeException("jdbc.properties 文件未找到!");
}
pro.load(input);
}
// 3. 获取配置值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
// 4. 注册驱动
Class.forName(driver);
} catch (Exception e) {
throw new RuntimeException("加载 JDBC 配置失败", e);
}
}
/**
* 获取数据库连接
*
* @return Connection 对象
* @throws SQLException 如果连接失败
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
/**
* 关闭资源
*
* @param resources 需要关闭的资源(Connection、Statement、ResultSet 等)
*/
public static void close(AutoCloseable... resources) {
for (AutoCloseable resource : resources) {
if (resource != null) {
try {
resource.close();
} catch (Exception e) {
throw new RuntimeException("关闭资源失败", e);
}
}
}
}
}
1.1 改进点总结
-
配置文件加载:使用
ClassLoader.getResourceAsStream()
直接加载资源文件,避免路径问题。 -
异常处理:统一处理异常,并包装为运行时异常。
-
资源关闭:使用可变参数和
AutoCloseable
接口简化资源关闭逻辑。 -
健壮性:增加对配置文件是否存在的检查。
AutoCloseable
是 Java 中的一个接口,定义在 java.lang
包中。它是 Java 7 引入的一个特性,用于支持 自动资源管理(ARM,Automatic Resource Management),通常与 try-with-resources
语句结合使用。
1.2 AutoCloseable 的作用
AutoCloseable
接口的核心方法是 close()
,用于释放资源。任何实现了 AutoCloseable
接口的类,都可以在 try-with-resources
语句中自动关闭资源,而无需显式调用 close()
方法。
public interface AutoCloseable {
void close() throws Exception;
}
1.3 AutoCloseable 的实现类
在 Java 中,许多与资源相关的类都实现了
AutoCloseable
接口,例如:
java.io.InputStream
、java.io.OutputStream
(文件流)
java.sql.Connection
、java.sql.Statement
、java.sql.ResultSet
(数据库相关)
java.nio.channels.Channel
(NIO 通道)
1.4 为什么使用 AutoCloseable?
在 Java 7 之前,资源管理通常需要手动调用
close()
方法,并在finally
块中确保资源被关闭。这种方式容易出错,比如忘记关闭资源或关闭资源的顺序不对。通过
AutoCloseable
和try-with-resources
,可以简化资源管理,确保资源在使用完毕后自动关闭,即使发生异常也不会遗漏。
1.5 使用示例
public class Main {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 获取连接
conn = JDBCUtils.getConnection();
// 创建 Statement
stmt = conn.createStatement();
// 执行查询
rs = stmt.executeQuery("SELECT * FROM users");
// 处理结果集
while (rs.next()) {
System.out.println(rs.getString("username"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JDBCUtils.close(rs, stmt, conn);
}
}
}
2.传统方式
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String url; // 只有静态变量,才能被静态代码块、静态方法访问。
private static String user;
private static String password;
private static String driver;
/**
* 配置文件的读取,只需要读取一次即可拿到这些值。使用静态代码块(随着类的加载而加载)
*/
static { // 静态代码块,只能解决异常,不能抛异常
// 读取资源文件,获取值。
try {
// 1. 创建 Properties 集合类
Properties pro = new Properties();
//获取src路径下的文件的方式-->ClassLoader 类加载器,可将字节码文件加载到内存,也可以后去src下的资源路径
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");// 返回的是一个文件的绝对路径
String path = res.getPath();// 返回字符串路径
// System.out.println(path); // 打印字符串路径
// 2. 加载文件
pro.load(new FileReader(path));
// 3. 获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
// 4. 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
*
* @return 连接对象
*/
public static Connection getConnection() throws SQLException { // 工具类一般都是静态的
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
*
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
END