之前已经提出了类似的问题,我经历了所有这些问题但却无法解决问题。相关问题 - Q1,Q2,Q3,Q4,Q5,Q6
我有一个Spring Batch项目,使用Spring Boot并尝试使用数据库连接池。我使用的是版本为8.5.x的嵌入式tomcat容器。
如果我使用application.properties指定数据源和池设置,一切正常。
但是当我尝试使用JNDI时,我得到了异常 -
Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
我在Maven jar中看不到任何jar名tomcat-dbcp-**
,因此我不确定是否需要包含任何新的依赖项或需要设置默认数据源工厂以及如何进行操作。
以下是我设置的JNDI bean Question。我已经消除了某些价值观。
@Bean
public TomcatEmbeddedServletContainerFactory embeddedServletContainerFactory(){
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("jdbc/myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "com.ibm.db2.jcc.DB2Driver");
resource.setProperty("url", "url");
resource.setProperty("username", "user");
resource.setProperty("password", "*****");
context.getNamingResources().addResource(resource);
}
};
}
@Lazy
@Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/myDataSource");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<groupId>***</groupId>
<artifactId>***</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>db2</groupId>
<artifactId>db2jcc</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>db2</groupId>
<artifactId>db2jcc_license_cu</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.0.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
答案 0 :(得分:11)
我通过在factory
定义中设置Resource
属性来解决问题。 resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
@Bean
public TomcatEmbeddedServletContainerFactory embeddedServletContainerFactory(){
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("jdbc/myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
resource.setProperty("driverClassName", "com.ibm.db2.jcc.DB2Driver");
resource.setProperty("url", "url");
resource.setProperty("username", "user");
resource.setProperty("password", "*****");
context.getNamingResources().addResource(resource);
}
};
}
根据tomcat 8文档,它应该通过查看DataSource
类型自动推断数据库池工厂类型,并且它以某种方式默认为DBCP工厂,并且该类在我的类路径中不存在。
我想这个问题可以通过使tomcat-dbcp-**
罐可用来解决,但我不知道如何使用spring boot或者即使弹簧启动可以实现。
我发现奇怪的是Spring Boot不包括tomcat-dbcp依赖项作为启动POM的一部分,但使用DBCP DataSource工厂作为默认工厂。
答案 1 :(得分:3)
如果你的话,“Starter POM”不再包含jndi reltead依赖项 正在使用Tomcat / Jetty / etc ...使用JNDI,您现在需要自己直接添加此依赖项。
然后在application.properties文件中配置JNDI
spring.datasource.jndi-name=java:comp/env/jdbc/yourname
对于您的例外,您需要将tomcat-dbcp添加到您的pom.xml文件中。
但是如果使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa'starters',你可以查看你的项目依赖项 将自动获得对&#34; tomcat-jdbc&#34;。
的依赖答案 2 :(得分:1)
您有多种选择:
1)要使用Apache JDBC数据源,不需要添加任何依赖项,因为它已在Tomcat Spring Boot启动程序中提供,但是您必须将默认工厂类更改为org.apache.tomcat.jdbc.pool.DataSourceFactory
才能使用它。
您可以在资源声明中做到这一点:
resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
我将在下面解释在何处添加此行。
2)要使用DBCP 2数据源(默认情况下实际上是期望的),需要依赖项:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>8.5.4</version>
</dependency>
当然,请根据您的Spring Boot Tomcat嵌入式版本调整构件版本。
3)要使用任何其他数据源,我将用HikariCP进行说明,如果配置中不存在所需的依赖项,则添加它(如果您依赖Spring Boot的持久性启动程序,则可能是HikariCP):
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.1.0</version>
</dependency>
并在资源声明中指定随附的工厂:
resource.setProperty("factory", "com.zaxxer.hikari.HikariDataSource");
例如对于PostgreSQL和DBCP 2数据源,请不要指定任何工厂,因为它是默认工厂:
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
//...
context.getNamingResources()
.addResource(resource);
}
这是Tomcat JDBC和HikariCP数据源的变体。
在postProcessContext()
中,按照前面针对Tomcat JDBC ds的说明设置工厂属性:
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
//...
resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
//...
context.getNamingResources()
.addResource(resource);
}
};
对于HikariCP:
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
//...
resource.setProperty("factory", "com.zaxxer.hikari.HikariDataSource");
//...
context.getNamingResources()
.addResource(resource);
}
};