我正在开发 Spring Boot 应用程序,我尝试使用 JNDI 连接数据源,但它不起作用,并给出以下错误,如果有人知道原因,请帮助:
这是它显示的错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'i': Invocation of init method failed;
nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object;
nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter,
or in an application resource file: java.naming.factory.initial
对于 pom.xml 依赖项文件,我包含了以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- Added from here -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.25</version>
</dependency>
当我使用 postgresql 数据库时,我使用了它的依赖项,并且在 application.properties 文件中我提到如下:
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
# Datasource settings
spring.datasource.initialize=true
spring.datasource.jndi-name=jdbc/IDB
spring.jmx.enabled: false
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=ROOT
spring.datasource.type=javax.sql.DataSource
spring.datasource.separator=;
对于 tomcat 上下文命名初始化,我定义了 bean,如下所示:
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
tomcat.enableNaming();
try {
tomcat.addContext("/aiv/appimages", imgLoc);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(org.apache.catalina.Context context) {
ContextResource resource = new ContextResource();
resource.setName("jdbc/ActiveIDB");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "org.postgresql.Driver");
resource.setProperty("url", "jdbc:postgresql://localhost:5432/postgres");
resource.setProperty("username", "postgres");
resource.setProperty("password", "ROOT");
context.getNamingResources().addResource(resource);
}
};
}
@Bean(destroyMethod="")
public DataSource dataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/IDB");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
请任何人都可以让我知道我做错了什么,为什么它会给我这个错误。已获得帮助。
最佳答案
你必须做 5 件事:
- tomcat.enableNaming();
- 将 ContextResource 添加到 NamingResources(使用相同的名称:jdbc/IDB 和 jdbc/ActiveIDB 具有不同的哈希代码:))
- spring.datasource.jndi-名称:jdbc/DS_NAME
- 将 org.springframework:spring-jdbc(EmbeddedDatabaseType 类)添加到类路径(它将激活 JndiDataSourceAutoConfiguration)
此时,spring将尝试创建数据源但失败,因为org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory类不在类路径中(它是javax的默认工厂.sql.DataSource资源)
- 添加依赖项org.apache.tomcat:tomcat-dbcp:8.5.4 [或更高版本](它包含org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory)
package com.example;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.context.annotation.Bean;
import javax.servlet.ServletException;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
@SpringBootApplication
public class Application {
/**
* Or you can copy full implementation from
* org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration.EmbeddedTomcat
* override only getTomcatWebServer(Tomcat)
* and provide TomcatContextCustomizer instead of overriding 'postProcessContext(Context)'
*/
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
//1 enable naming
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
//2 create resource
ContextResource resource = new ContextResource();
resource.setName("jdbc/h2DS");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "org.h2.Driver");
resource.setProperty("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
resource.setProperty("username", "sa");
resource.setProperty("password","");
context.getNamingResources().addResource(resource);
}
};
}
public static void main(String[] args) throws ServletException, IOException, SQLException {
//3 JndiDataSourceAutoConfiguration will provide that bean if
// a) spring.datasource.jndi-name: jdbc/h2DS
// b) org.springframework:spring-jdbc (class EmbeddedDatabaseType) is in classpath
SpringApplication.run(Application.class, args)
.getBean(DataSource.class)
.getConnection();
}
}
依赖关系
- org.springframework.boot:spring-boot-starter-web
- org.springframework:spring-jdbc
- com.h2database:h2:2.1.214(运行时)
- org.apache.tomcat:tomcat-dbcp:8.5.4 [或更高版本](运行时)
应用程序属性
spring.datasource.jndi-name=jdbc/h2DS
关于java - Spring boot JNDI不工作,tomcat无法启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72729120/