Servlet 拋出 `Servlet execution threw an exception`,根因指向 `DBConn` 類初始化。
public class DBConn {
static {
try {
// ❌ 這行無意義
DBConn.class.getClassLoader();
InputStream in = ClassLoader.getSystemResourceAsStream("joggle.properties");
// ❌ 若文件不在 classpath 根目錄,in 為 null
Properties prop = new Properties();
prop.load(in); // ❌ NPE:in 為 null
// ...
} catch (Exception e) {
throw new ExceptionInInitializerError(e); // 包裝拋出
}
}
// ...
}
public class DBConn {
private static final Logger log = LoggerFactory.getLogger(DBConn.class);
private static final String PROP_FILE = "jdbc.properties"; // 建議標準名
static {
try (InputStream in = DBConn.class.getClassLoader().getResourceAsStream(PROP_FILE)) {
if (in == null) {
throw new RuntimeException("配置文件未找到: " + PROP_FILE + ",請放置在 classpath 根目錄");
}
Properties prop = new Properties();
prop.load(in);
driverName = prop.getProperty("driverName");
dbURL = prop.getProperty("dbURL");
userName = prop.getProperty("userName");
password = prop.getProperty("password");
Class.forName(driverName);
log.info("數據庫驅動加載成功: {}", driverName);
} catch (Exception e) {
log.error("DBConn 初始化失敗", e);
throw new ExceptionInInitializerError(e);
}
}
// 連接池建議使用 HikariCP / Druid,而非手寫
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(dbURL, userName, password);
}
}
Maven 標準結構:
src/
main/
resources/
jdbc.properties ← 這裡
java/
com/...
DBConn.java
driverName=com.mysql.cj.jdbc.Driver
dbURL=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
userName=root
password=123456
com.zaxxer
HikariCP
5.0.1
// Spring 配置
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbURL);
config.setUsername(userName);
config.setPassword(password);
config.setDriverClassName(driverName);
config.setMaximumPoolSize(20);
return new HikariDataSource(config);
}
`ExceptionInInitializerError` 包裝了真實異常(此處為 NPE)。**關鍵定位:查看 `Caused by` 鏈最底層的異常**。配置文件路徑、靜態塊異常處理、資源流關閉、遷移到成熟連接池,四步徹底解決。