Web應用啟動時初始化數據庫連接池,放入ServletContext全局共享,是JSP/Servlet時代的標準模式。本文演示基於ServletContextListener、MySQLMysqlConnectionPoolDataSource、JSTL<sql:query>的完整鏈路(環境:Tomcat 5.5 + MySQL 4.1 + mysql-connector-java 3.1.13)。
ResourceManagerListener)package kinglong.jmediasoft.servlets;
import javax.servlet.*;
import com.mysql.jdbc.jdbc2.optional.*;
public class ResourceManagerListener implements ServletContextListener {
private DataSource ds = null;
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext application = sce.getServletContext();
// 從web.xml context-param讀取配置
String jdbcUrl = application.getInitParameter("jdbcURL");
String user = application.getInitParameter("user");
String password = application.getInitParameter("password");
try {
// MySQL連接池數據源
ds = new MysqlConnectionPoolDataSource();
ds.setUrl(jdbcUrl);
ds.setUser(user);
ds.setPassword(password);
} catch (Exception e) {
application.log("無法創建數據源:" + e.getMessage());
return;
}
// 放入Application作用域,全WebApp可見
application.setAttribute("dataSource", ds);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContext application = sce.getServletContext();
application.removeAttribute("dataSource");
ds = null; // 協助GC
}
}
<context-param>
<param-name>jdbcURL</param-name>
<param-value>jdbc:mysql://localhost:3306/comic</param-value>
</context-param>
<context-param>
<param-name>user</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>
<listener>
<listener-class>kinglong.jmediasoft.servlets.ResourceManagerListener</listener-class>
</listener>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="sql" uri="https://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="fn" uri="https://java.sun.com/jsp/jstl/functions" %>
<!-- 從Application作用域獲取數據源執行查詢 -->
<sql:query var="comicinfo" dataSource="${applicationScope.dataSource}" sql="SELECT * FROM comicinfo" />
<html><head><title>數據庫測試頁面</title></head><body>
<table>
<c:forEach items="${comicinfo.rows}" var="row">
<c:forEach items="${row}" var="column">
<tr>
<td align="right"><b>${fn:escapeXml(column.key)}:</b></td>
<td align="left">${fn:escapeXml(column.value)}</td>
</tr>
</c:forEach>
</c:forEach>
</table>
</body></html>
contextInitialized在WebApp啟動、處理請求前執行,保證數據源就緒。applicationScope.dataSource跨全WebApp共享,避免重複創建連接池。dataSource="${applicationScope.dataSource}"直接引用EL可見的數據源對象,無需JNDI查找。mysql-connector-java-3.1.13-bin.jar放入WEB-INF/lib或Tomcatcommon/lib。contextDestroyed移除屬性、置空引用,配合連接池自身close()釋放物理連接。| 傳統模式 | 現代模式 |
|---|---|
| Listener手動創建DataSource | Spring Boot spring.datasource.* 自動配置 HikariCP |
application.setAttribute共享 | Spring Bean單例注入 @Autowired DataSource |
JSTL <sql:query>頁面直連 | Service層 JdbcTemplate/MyBatis + Controller傳DTO給View |
| web.xml配置參數 | application.yml / application.properties |
| MySQL Connector/J 3.x | 8.0+ (驅動類 com.mysql.cj.jdbc.Driver、URL jdbc:mysql://host:3306/db?useSSL=false&serverTimezone=UTC) |
<context-param>
<param-name>jdbcURL</param-name>
<param-value>jdbc:mysql://localhost:3306/comic?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai</param-value>
</context-param>
連接池參數(HikariCP):maximumPoolSize=20、minimumIdle=5、idleTimeout=300000、connectionTimeout=30000、maxLifetime=1800000、connectionTestQuery=SELECT 1。
Listener初始化數據源是JSP/Servlet時代「啟動即備、全局共享、銷毀釋放」資源管理的教科書級模式。理解其生命週期邊界與作用域語義,對遷移現代依賴注入容器極有幫助。