记录SpringBoot环境下内置Tomcat,基于JNDI获取DataSource方式遇到的报错

前言

我司项目是使用外部Tomcat,配置DataSource获取数据源的方式
有一个factory的配置为org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory。但在对项目微服务化改造的过程中报错:Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory
springboot.version: 2.3.4.RELEASE

解决错误历程

Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_202]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_202]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_202]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_202]
	at org.apache.naming.factory.FactoryBase.getObjectInstance(FactoryBase.java:65) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	... 43 common frames omitted

旧工程使用的tomcat版本是:tomcat7版本
新工程使用的内置tomcat版本是:tomcat9
查阅Tomcat9.JNDI资源将factory的值改为:org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory继续报错:

Caused by: javax.naming.NamingException: Found a circular reference involving [java:comp/env/jdbc/testMassData]
	at org.apache.naming.factory.LookupFactory.getObjectInstance(LookupFactory.java:76) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321) ~[na:1.8.0_202]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:857) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:174) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.SelectorContext.lookup(SelectorContext.java:163) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at javax.naming.InitialContext.lookup(InitialContext.java:417) ~[na:1.8.0_202]
	at org.apache.naming.factory.LookupFactory.getObjectInstance(LookupFactory.java:127) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321) ~[na:1.8.0_202]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:857) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:160) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:843) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.NamingContext.lookup(NamingContext.java:174) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at org.apache.naming.SelectorContext.lookup(SelectorContext.java:163) ~[tomcat-embed-core-9.0.38.jar:9.0.38]
	at javax.naming.InitialContext.lookup(InitialContext.java:417) ~[na:1.8.0_202]
	at com.jndi.embedded.dal.DalAutoConfiguration.dataSource(DalAutoConfiguration.java:31) ~[classes/:na]
	... 31 common frames omitted

最后,在pom.xml中添加apache的commons-dbcp依赖,仍然报上述错误。
最终,继续将factory的值修改为org.apache.commons.dbcp.BasicDataSourceFactory且ContextResource中不对lookupName设值解决上述问题。

总结

  1. 当对ContextResource的lookupName设值:JndiLocatorSupport.CONTAINER_PREFIX + "jdbc/testMassData"的时候会报错误:
    Found a circular reference involving [java:comp/env/jdbc/testMassData]
  2. 当对ContextResource,不设置factory属性时,报错:
    Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
  3. 正确使用JNDI方式:pom.xml引入commons-dbcp 且 内置Tomcat的ContextResource中需要对factory值赋值,并不设置lookupName属性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Tomcat中配置JNDI,你可以按照以下步骤进行操作: 1. 打开Tomcat的配置文件`tomcat/conf/server.xml`。 2. 在`<GlobalNamingResources>`元素中配置全局资源,例如数据库连接池。例如,你可以添加一个`<Resource>`元素来定义一个连接池: ```xml <GlobalNamingResources> <Resource name="jdbc/myDataSource" auth="Container" type="javax.sql.DataSource" maxTotal="100" maxIdle="30" maxWaitMillis="10000" username="your_username" password="your_password" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/your_database"/> </GlobalNamingResources> ``` 在上面的示例中,我们定义了一个名为`jdbc/myDataSource`的资源,它是一个`javax.sql.DataSource`类型的数据库连接池。 3. 在`<Context>`元素中引用全局资源。在你的Web应用程序的上下文配置文件(通常是`META-INF/context.xml`)中,你可以使用`<ResourceLink>`元素引用全局资源。例如: ```xml <Context> <ResourceLink name="jdbc/myLocalDataSource" global="jdbc/myDataSource" type="javax.sql.DataSource"/> </Context> ``` 在上面的示例中,我们将全局资源`jdbc/myDataSource`映射到本地资源`jdbc/myLocalDataSource`。 4. 在你的应用程序中使用JNDI查找资源。你可以通过在代码中使用JNDI查找资源来获取连接池实例。例如,在Java中可以这样做: ```java Context initContext = new InitialContext(); Context envContext = (Context) initContext.lookup("java:/comp/env"); DataSource dataSource = (DataSource) envContext.lookup("jdbc/myLocalDataSource"); Connection connection = dataSource.getConnection(); ``` 在上面的示例中,我们通过JNDI查找资源`jdbc/myLocalDataSource`来获取`javax.sql.DataSource`实例,并从中获取数据库连接。 请注意,这只是一个基本的示例,具体的配置和使用方法可能会因你的需求和环境而有所不同。你可以根据你的实际情况进行相应的调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值