TongWeb 7.0.C 容器版数据源配置实战:从 JNDI 到 Spring 的深度解析
最近在帮客户做系统迁移时,遇到了一个让人头疼的问题:原本在企业版 TongWeb 上运行良好的应用,迁移到 7.0.C 容器版后,数据源配置突然失效了。经过一番折腾才发现,原来容器版的数据源访问方式与企业版有着微妙但关键的区别。本文将分享我在这个过程中的发现和解决方案。
1. 容器版与传统版的 JNDI 数据源差异
TongWeb 7.0.C 容器版最显著的变化之一就是 JNDI 查找路径的调整。对于习惯了企业版或标准版的开发者来说,这个变化可能会带来一些困惑。
1.1 传统版与容器版的 JNDI 路径对比
传统版本(企业版/标准版)的 JNDI 查找方式:
Context initialContext = new InitialContext(); DataSource dataSource = (DataSource)initialContext.lookup("jdbc/testdb");而容器版则采用了类似 Tomcat 的方式:
Context initialContext = new InitialContext(); DataSource dataSource = (DataSource)initialContext.lookup("java:comp/env/jdbc/testdb");这个差异看似微小,却会导致应用在迁移时出现找不到数据源的问题。关键区别在于容器版需要在 JNDI 名称前添加java:comp/env/前缀。
1.2 配置文件的对应调整
为了支持新的查找方式,我们需要对配置文件做相应修改:
- web.xml中需要添加资源引用:
<resource-ref> <description>jdbc/testdb</description> <res-ref-name>jdbc/testdb</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>- tongweb-web.xml(容器版特有)需要放置在 WEB-INF 目录下:
<?xml version="1.0" encoding="UTF-8"?> <tongweb-web-app> <resource-links> <resource-link name="jdbc/testdb" type="javax.sql.DataSource" global="jdbc/testdb" /> </resource-links> </tongweb-web-app>注意:如果只是简单地在 lookup 前加上 java:comp/env 前缀,可以不用配置 tongweb-web.xml。但如果需要改变 lookup 名称,则必须配置。
2. 与 Spring 框架的集成实践
在实际项目中,我们通常会使用 Spring 框架来管理数据源。TongWeb 容器版的数据源与 Spring 集成时也有一些需要注意的地方。
2.1 使用 JndiObjectFactoryBean
Spring 提供了JndiObjectFactoryBean来简化 JNDI 资源的获取。针对容器版,配置方式如下:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <!-- 容器版必须使用完整路径 --> <value>java:comp/env/jdbc/testdb</value> </property> </bean>相比之下,传统版本的配置则更简单:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <!-- 传统版直接使用短名称 --> <value>jdbc/testdb</value> </property> </bean>2.2 多环境适配策略
为了支持应用在不同版本的 TongWeb 上运行,可以采用条件配置的方式:
@Configuration public class DataSourceConfig { @Value("${tongweb.version}") private String tongwebVersion; @Bean public DataSource dataSource() throws Exception { JndiObjectFactoryBean factory = new JndiObjectFactoryBean(); if ("container".equals(tongwebVersion)) { factory.setJndiName("java:comp/env/jdbc/testdb"); } else { factory.setJndiName("jdbc/testdb"); } factory.afterPropertiesSet(); return (DataSource) factory.getObject(); } }或者使用 Spring 的 profile 机制:
<beans profile="container"> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/testdb"/> </bean> </beans> <beans profile="enterprise"> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="jdbc/testdb"/> </bean> </beans>3. 连接池配置优化指南
无论使用哪种数据源,连接池的合理配置都是保证系统稳定性的关键。以下是几个必须关注的参数:
| 参数名称 | 作用说明 | 推荐设置 | 注意事项 |
|---|---|---|---|
| 初始连接数 | 连接池启动时创建的连接数 | 5-10 | 不宜过大,避免启动时资源浪费 |
| 最大连接数 | 连接池允许的最大连接数 | 根据DB能力设置 | 必须小于数据库最大连接数 |
| 测试SQL | 验证连接有效性的SQL | SELECT 1 | 应使用最简单高效的SQL |
| 获取连接超时 | 等待获取连接的最长时间 | 30000(30秒) | 避免无限等待导致线程阻塞 |
| 空闲连接检测 | 定期检测空闲连接是否有效 | 300000(5分钟) | 防止使用已失效的连接 |
3.1 常见问题排查
连接池耗尽错误:
java.sql.SQLTransientConnectionException: testdb - Numbers of connections reached pool maxsize: {testdb}stats (total=10}, active={10} idle={0} waiting={0}) ,so request timed out after 30000ms.解决方案:
- 检查是否有连接泄漏(未正确关闭)
- 适当增加最大连接数(但不超过数据库限制)
- 优化SQL性能,减少连接占用时间
连接阻塞问题:
"httpWorkerThread-9060-63" #104 daemon prio=10 os_prio=0 tid=0x0000007ec007c800 nid=0x700e waiting for monitor entry [0x0000007deebfb000] java.lang.Thread.State: BLOCKED (on object monitor)这通常是由于未设置获取连接超时时间导致的。确保配置了合理的超时时间。
4. 容器版特有问题的解决方案
在 TongWeb 7.0.C 容器版的实际使用中,我遇到了几个特有的问题,这里分享解决方案。
4.1 类加载器问题
容器版采用了不同的类加载机制,这可能导致某些数据库驱动无法加载。解决方法是将驱动 jar 包放置在以下位置之一:
$TONGWEB_HOME/lib目录- 应用的
WEB-INF/lib目录 - 通过
SharedLib配置共享库
提示:推荐将数据库驱动放在应用本身的 WEB-INF/lib 下,这样可以避免不同应用间的版本冲突。
4.2 热部署时的连接泄漏
容器版在热部署时可能会出现连接未正确关闭的情况。可以通过以下方式检测:
- 在应用的
contextDestroyed方法中添加连接池状态日志 - 配置连接池的泄漏检测参数:
# 对于Druid数据源 spring.datasource.druid.removeAbandoned=true spring.datasource.druid.removeAbandonedTimeout=1800 spring.datasource.druid.logAbandoned=true4.3 性能监控配置
容器版提供了更丰富的监控指标,可以通过以下方式开启:
- 在
tongweb-web.xml中添加:
<monitoring> <jdbc enabled="true"/> </monitoring>- 访问管理控制台的
/monitor页面查看数据源状态
5. 最佳实践与经验分享
经过多个项目的实践,我总结出以下 TongWeb 容器版数据源配置的最佳实践:
版本明确原则:在项目文档中明确标注使用的 TongWeb 版本类型(容器版/企业版),避免团队成员混淆。
配置分离策略:
- 将数据源配置与业务代码分离
- 使用环境变量或外部配置文件管理连接参数
- 为不同环���(开发、测试、生产)准备不同的配置
连接池选择建议:
- 如果使用 TongWeb 内置连接池,确保了解其特性
- 考虑使用成熟的开源连接池如 HikariCP
- 避免在同一个应用中混用多种连接池
故障排查工具箱:
- 准备常用的诊断SQL(如查看数据库连接数)
- 记录连接池的关键指标(活跃数、空闲数、等待数)
- 设置合理的日志级别以便排查问题
迁移检查清单: 当从传统版迁移到容器版时,务必检查:
- JNDI 查找路径是否已更新
- 配置文件是否已调整
- 所有依赖的驱动是否可用
- 监控指标是否正常
在实际项目中,我发现最容易出错的地方往往是最基础的配置项。例如,有一次因为疏忽了容器版必须使用完整 JNDI 路径的规则,导致团队花了整整一天时间排查问题。这也让我深刻体会到,对于中间件版本差异的细节把握有多么重要。