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: root2、创建一个配置类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相关的报错问题,如果有任何进一步的问题,欢迎随时提问。
