Tomcat 8.5中JNDI DataSource查找失败问题求助
问题原因及正确配置方式
问题根源
你当前的配置存在冲突:Tomcat中,当在server.xml的<Host>节点下直接定义了指定path="/app1"的<Context>时,Tomcat会忽略conf/Catalina/localhost/app1.xml这个独立上下文配置文件。这就导致app1.xml里定义的jdbc/APP1OS数据源根本没被加载,自然会出现JNDI查找失败的报错。
简单来说:同一上下文路径的配置,server.xml中的硬编码配置优先级高于localhost目录下的XML文件,后者直接被跳过,数据源也就没注册到JNDI容器中。
正确配置方案
有两种规范配置方式,任选其一即可:
方案一:仅使用独立上下文配置文件(推荐)
删掉server.xml中<Host>下的<Context>节点,只保留conf/Catalina/localhost/app1.xml的配置:
- 修改后的
server.xmlHost部分:
<Host appBase="webapps" deployOnStartup="false" autoDeploy="false" name="localhost" unpackWARs="true"> <!-- 移除原有的<Context>节点 --> </Host>
- 保留
app1.xml的完整配置(包含数据源Resource):
<Context displayName="Application One" path="/app1" swallowOutput="true"> <Resource name="jdbc/APP1OS" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.cj.jdbc.Driver" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" maxActive="100" maxIdle="10" maxWait="5000" maxAge="60000" username="username" password="password" url="jdbc:mysql://dbname:port/appint?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&characterSetResults=utf8&serverTimezone=UTC&socketTimeout=300000&useSSL=false&requireSSL=false&allowPublicKeyRetrieval=true" testOnBorrow="true" validationQuery="Select '1'"/> </Context>
这种方式是Tomcat官方推荐的配置方式,避免直接修改server.xml(server.xml修改后需重启整个Tomcat,而独立上下文文件支持热加载)。
方案二:在server.xml中统一配置(适合全局共享资源场景)
如果一定要保留server.xml中的<Context>节点,可将数据源Resource直接定义在该<Context>内部(即你已经验证有效的方式),或者通过<ResourceLink>引用全局数据源:
- 先在
server.xml的<GlobalNamingResources>下定义全局数据源:
<GlobalNamingResources> <Resource name="jdbc/APP1OSGlobal" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.cj.jdbc.Driver" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" maxActive="100" maxIdle="10" maxWait="5000" maxAge="60000" username="username" password="password" url="jdbc:mysql://dbname:port/appint?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&characterSetResults=utf8&serverTimezone=UTC&socketTimeout=300000&useSSL=false&requireSSL=false&allowPublicKeyRetrieval=true" testOnBorrow="true" validationQuery="Select '1'"/> </GlobalNamingResources>
- 再在server.xml的
<Context>中添加ResourceLink:
<Host appBase="webapps" deployOnStartup="false" autoDeploy="false" name="localhost" unpackWARs="true"> <Context displayName="Application One" path="/app1" reloadable="true"> <ResourceLink name="jdbc/APP1OS" global="jdbc/APP1OSGlobal" type="javax.sql.DataSource"/> </Context> </Host>
这种方式适合多个应用共享同一数据源的场景,但修改server.xml需要重启Tomcat,灵活性较差。
额外注意事项
- 确保MySQL驱动jar包放在
Tomcat/lib目录下,不要放在应用的WEB-INF/lib中,否则容器级数据源会加载失败。 - 确认
deployOnStartup="false"和autoDeploy="false"的配置,避免Tomcat自动部署webapps下的应用,与手动配置的上下文产生冲突。
内容的提问来源于stack exchange,提问作者arunK
相关产品推荐
相关产品推荐

