在Java Web开发领域,数据源连接管理一直是影响应用性能的关键因素。传统JDBC直连方式存在两大痛点:一是每次请求都需建立物理连接,在高并发场景下会导致数据库连接数暴增;二是连接参数硬编码在应用中,变更时需要重新部署。JNDI(Java Naming and Directory Interface)数据源通过连接池技术和集中式配置,完美解决了这些问题。
Tomcat作为轻量级应用服务器的代表,提供了三种主流配置方式:
生产环境推荐使用全局配置+应用覆盖的组合策略,既保证统一管理又兼顾特殊需求
全局配置位于$CATALINA_HOME/conf/context.xml,配置对所有部署的应用生效。典型配置示例如下:
xml复制<Context>
<Resource name="jdbc/mydb"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="dbuser"
password="dbpass"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?useSSL=false"/>
</Context>
连接池控制:
数据库配置:
xml复制<Resource ... password="${db.password}"/>
配合$CATALINA_HOME/conf/catalina.properties中的密文配置
xml复制<Resource ... url="${db.url}"/>
通过启动参数-Ddb.url=jdbc:mysql://dev-db:3306/mydb动态指定
应用专属配置存放于:
code复制/WEB-INF/context.xml (推荐)
/META-INF/context.xml
xml复制<Context path="/myapp">
<Resource name="jdbc/appdb"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
initialSize="5"
minIdle="5"
maxActive="20"
jdbcInterceptors="ConnectionState;StatementCache(max=200)"/>
</Context>
应用级配置会覆盖全局同名资源,适合测试环境与特殊需求场景
xml复制initialSize="5" minIdle="5"
避免首次请求时的连接建立延迟
xml复制jdbcInterceptors="StatementCache(max=200)"
对高频查询语句进行缓存
java复制Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
envCtx.bind("jdbc/dynamicDB", createDataSource());
java复制private DataSource createDataSource() {
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:mysql://localhost/test");
p.setDriverClassName("com.mysql.jdbc.Driver");
p.setInitialSize(5);
p.setMaxActive(20);
return new DataSource(p);
}
| 场景特征 | 推荐配置 | 说明 |
|---|---|---|
| 低并发OLTP | maxTotal=20, maxIdle=10 | 常规Web应用 |
| 高并发查询 | maxTotal=100, maxWait=5000 | 电商秒杀场景 |
| 批量处理 | maxTotal=50, removeAbandoned=true | 防止长时间占用连接 |
xml复制<Resource ... jmxEnabled="true"/>
通过JConsole查看连接池状态
xml复制<Resource ... removeAbandoned="true"
removeAbandonedTimeout="300"
logAbandoned="true"/>
$CATALINA_HOME/libjava复制@Resource(lookup="java:comp/env/jdbc/master")
private DataSource masterDS;
@Resource(lookup="java:comp/env/jdbc/slave")
private DataSource slaveDS;
xml复制<Resource factory="com.zaxxer.hikari.HikariJNDIFactory"
type="javax.sql.DataSource"
jdbcUrl="jdbc:mysql://localhost/db"
poolName="springHikariCP"/>
xml复制<Resource factory="com.alibaba.druid.pool.DruidDataSourceFactory"
filters="stat,wall"
maxActive="20"
validationQuery="SELECT 'x'"/>
xml复制<Resource ... url="${DB_URL}"
username="${DB_USER}"
password="${DB_PASSWORD}"/>
配合Secret对象管理凭证
sql复制-- 数据库用户只授予必要权限
GRANT SELECT, INSERT ON mydb.* TO 'appuser'@'%';
xml复制<Resource ... url="jdbc:mysql://dbserver:3306/mydb?useSSL=true&requireSSL=true"/>
xml复制<Resource ... logAbandoned="true"
abandonWhenPercentageFull="50"/>
| Tomcat版本 | 特性变化 |
|---|---|
| 7.x | 默认使用commons-dbcp |
| 8.x | 引入tomcat-jdbc连接池 |
| 9.x | 支持JDBC 4.2规范 |
| 10.x | Jakarta EE 9命名空间变更 |
升级注意事项:
- Tomcat 10+需使用
jakarta前缀- 验证驱动兼容性(如MySQL 8.x需要新驱动)