JNDI报错详解及解决方案
一、JNDI
Java Naming and Directory Interface(JNDI)是Java EE标准之一,用于为Java应用程序提供命名和目录功能,它提供了一种统一的接口,允许应用程序与各种命名和目录服务进行交互,通过JNDI,开发人员可以使用不同的访问协议(如LDAP、RMI、CORBA等)来查找并操作资源对象。

二、常见JNDI报错及解决方案
1. javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
报错信息:
- javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
原因分析:
这个错误通常表明在当前的上下文环境中找不到名为jdbc
的数据源,这可能是因为数据源未正确配置或绑定到当前上下文。
解决方案:
检查配置文件: 确保在Tomcat的server.xml
或项目的context.xml
中正确配置了数据源。

- <Context>
- <Resource name="jdbc/myDataSource" auth="Container" type="javax.sql.DataSource"
- maxTotal="20" maxIdle="10" maxWaitMillis="1"
- username="root" password="password" driverClassName="com.mysql.jdbc.Driver"
- url="jdbc:mysql://localhost:3306/mydatabase"/>
- </Context>
确保web.xml配置正确: 在项目的web.xml
中添加以下配置:
- <resourceref>
- <description>My JDBC Data Source</description>
- <resrefname>jdbc/myDataSource</resrefname>
- <restype>javax.sql.DataSource</restype>
- <resauth>Container</resauth>
- </resourceref>
重新部署项目: 确保所有更改已生效,并且项目已重新部署。
2. org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
报错信息:
- org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
原因分析:
此错误通常是由于缺少JDBC驱动程序或驱动类名拼写错误导致的,还可能是由于数据源配置错误。

解决方案:
添加JDBC驱动程序: 确保将相应的JDBC驱动程序jar文件添加到Tomcat的lib
目录中,对于MySQL数据库,需要添加mysqlconnectorjava.jar
。
检查驱动类名: 确保驱动类名正确无误,对于MySQL,驱动类名应为com.mysql.cj.jdbc.Driver
。
验证数据源配置: 确保在context.xml
或server.xml
中的配置信息正确无误。
- <Resource name="jdbc/myDataSource" auth="Container" type="javax.sql.DataSource">
- <ResourceParams name="factory" value="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
- <ResourceParams name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
- <ResourceParams name="url" value="jdbc:mysql://localhost:3306/mydatabase"/>
- <ResourceParams name="username" value="root"/>
- <ResourceParams name="password" value="password"/>
- <ResourceParams name="maxActive" value="20"/>
- <ResourceParams name="maxIdle" value="10"/>
- <ResourceParams name="maxWaitMillis" value="1"/>
- </Resource>
3. java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
报错信息:
- java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
原因分析:
此错误通常是由于缺少必要的依赖库或类路径未正确设置导致的。
解决方案:
添加依赖库: 确保项目中包含所需的依赖库,对于Maven项目,可以在pom.xml
中添加以下依赖:
- <dependency>
- <groupId>org.apache.tomcat</groupId>
- <artifactId>tomcatdbcp</artifactId>
- <version>8.5.4</version>
- <scope>provided</scope>
- </dependency>
检查类路径: 确保所有必要的类路径已正确添加到项目中,如果使用IDE,请确保构建路径中包含相关库。
三、FAQs
Q1: 如何在开发环境中解决Main方法无法注入JNDI的问题?
A1: 在开发环境中,可以通过配置Spring Boot的applicationdev.yml
文件来解决Main方法无法注入JNDI的问题,具体步骤如下:
1、创建applicationdev.yml
文件并添加以下内容:
- jndi:
- dev:
- driverclassname: com.mysql.jdbc.Driver
- url: jdbc:mysql://192.168.xxx.xxx:3306/test
- username: root
- password: root
2、创建一个配置类JndiDevConfig
:
- @Profile("dev")
- public class JndiDevConfig {
- @Value("${spring.datasource.jndiname}")
- private String jndiName;
- @Value("${jndi.dev.driverclassname}")
- private String driverClassName;
- @Value("${jndi.dev.url}")
- private String url;
- @Value("${jndi.dev.username}")
- private String username;
- @Value("${jndi.dev.password}")
- private String password;
- @Bean
- public ServletWebServerFactory servletContainer() {
- TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
- @Override
- protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
- tomcat.enableNaming();
- return super.getTomcatWebServer(tomcat);
- }
- @Override
- protected void postProcessContext(Context context) {
- ContextResource resource = new ContextResource();
- resource.setName(jndiName);
- resource.setType(DataSource.class.getName());
- resource.setProperty("driverClassName", driverClassName);
- resource.setProperty("url", url);
- resource.setProperty("username", username);
- resource.setProperty("password", password);
- context.getNamingResources().addResource(resource);
- super.postProcessContext(context);
- }
- };
- return tomcat;
- }
- }
3、确保在开发环境中启用该配置。
Q2: 如何在高版本的JDK中绕过JNDI远程加载限制?
A2: 在JDK的高版本中,默认禁用了远程加载,可以通过设置系统属性来绕过这一限制,具体步骤如下:
1、设置系统属性com.sun.jndi.rmi.object.trustURLCodebase
为true
:
- Dcom.sun.jndi.rmi.object.trustURLCodebase=true
2、如果使用的是Spring Boot项目,可以在application.properties
或application.yml
中添加以下配置:
- spring.jndi.rmi.object.trustURLCodebase=true
3、确保所有配置已生效,并重新运行应用程序。
通过以上详细的分析和解决方案,希望能够帮助你更好地理解和解决JNDI相关的报错问题,如果有任何进一步的问题,欢迎随时提问。