2016-09-02 156 views
2

以前也有過類似的問題,我經歷過所有這些,但無法解決問題。相關問題 - Q1Q2Q3Q4Q5Q6SpringBoot的JNDI數據源拋出java.lang.ClassNotFoundException:org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory

我和春天有引導Spring Batch的項目,並嘗試使用數據庫連接池。我正在使用版本8.5.x的嵌入式tomcat容器。

如果我使用application.properties指定數據源和池設置,那麼一切正常。

但是,當我嘗試使用JNDI,我得到的例外 -

Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory 

我看不出有任何的JAR名稱tomcat-dbcp-**在Maven的罐子,所以我不知道如果我需要包括任何新的依賴或需要設置默認的數據源工廠以及如何處理它。

以下是我設置的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

我不確定理由,被更高級別的人問到。可能他們不希望用戶名和密碼在屬性文件中。我發現奇怪的是,spring boot不包括tomcat-dbcp依賴項作爲啓動器POM的一部分,但是使用DBCP DataSource工廠作爲默認工廠。 –

+0

如果我們必須保持開放以部署到非嵌入式環境,是否有更好的方法來保護數據庫連接信息?我們通過類文件面臨的一個挑戰是編輯DB urls和用戶的各種登臺環境,但是用war文件分發db信息似乎不是一個好主意。 –

+1

您不必將其包含在文件中。您可以在啓動應用程序時將它作爲參數傳遞,或作爲環境變量傳遞。另外,如果您指定數據源jndi名稱,則將使用它而不是本地配置的實例。我建議閱讀Spring Boot如何加載/解析屬性文件以及如何爲環境指定屬性,而不是深入研究它。總之,你應該在框架內工作而不是框架。 –

回答

6

我通過在我的Resource定義中設置factory屬性解決了該問題。 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工廠自動推斷DB池工廠類型和類是不存在在我的類路徑中。

我想這樣的問題可以通過使tomcat-dbcp-**罐子可用來解決,但我不知道如何做到這一點與春季啓動,或者即使這是可能的彈簧引導。

我發現奇怪的是Spring Boot不包括tomcat-dbcp依賴項作爲啓動程序POM的一部分,但是使用DBCP DataSource工廠作爲默認工廠。

1

的「入門POM」不再包括JNDI reltead依賴關係,如果你 使用Tomcat /碼頭/等..使用JNDI,你現在需要直接自己添加這個依賴關係。

然後配置你的application.properties的JNDI文件 spring.datasource.jndi-name=java:comp/env/jdbc/yourname

爲了您的例外,你需要添加tomcat-dbcp到您的pom.xml文件。

但你可以檢查你的項目的依賴,如果你使用的彈簧引導啓動-JDBC或彈簧引導起動數據JPA「首發」你 將自動獲得一個依賴於「Tomcat的JDBC」。

+0

那些** jndi reltead依賴關係**?另外,我猜,我在bean定義中設置了相同的屬性。 –

+0

@SabirKhan請參閱更新,謝謝。 –