簡體   English   中英

在運行時添加 JDBC 驅動程序 - 引起:java.lang.ClassNotFoundException:com.mysql.jdbc.Driver

[英]Adding JDBC driver at runtime - Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

我試圖在運行時添加一個外部 jar,然后使用該 jar 連接到數據庫(而不是必須向 pom 添加許多驅動程序,目標是為用戶提供在運行時加載任何驅動程序 jar 的能力)。 我正在使用 spring boot 項目,我正在嘗試使用 spring boots DataSourceBuilder創建數據源。

Loading JDBC Driver at RuntimeLoading jars at runtime 中的答案和建議似乎不適用於以下代碼:

@Component
public class DriverLoader {

    private static final String URL = "jdbc:mysql://localhost:3306/sakila?useSSL=false";
    private static final String USER = "root";
    private static final String ADMIN = "admin";
    private static final String DRIVER_JAR = "C:\\Users\\Sander\\Downloads\\mysql-connector-java-5.1.40.jar";

    @PostConstruct
    private void loadDriver() throws Exception {
        File file = new File(DRIVER_JAR);
        if (file != null) {
            URLClassLoader URLClassLoader = new URLClassLoader(new URL[] {file.toURI().toURL()}, System.class.getClassLoader());
            String driverName = DatabaseDriver.fromJdbcUrl(URL).getDriverClassName();
            System.out.println(driverName);

            // lets try to load the class
            Class<?> driverClass = URLClassLoader.loadClass(driverName);
            Driver actualDriver = (Driver) driverClass.newInstance();
            URLClassLoader.close();

            // Throws: Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.StringUtils
            /*Properties properties = new Properties();
            properties.put("user", USER);
            properties.put("password", ADMIN);
            Connection con = actualDriver.connect(URL, properties);*/           

            DataSource dataSource = createNewDataSource(URL, USER, ADMIN);

            if (dataSource != null) {
                // lets try to connect
                // Throws: Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
                dataSource.getConnection().isValid(1);
            }           
        }       
    }

    public DataSource createNewDataSource(String url, String username, String password) {
        return DataSourceBuilder
                .create()
                .url(url)       
                .username(username)
                .password(password)
                .build();
    }    
}

我正在使用的 pom 片段:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>           
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

如果在運行時添加了 jar 文件,如何使用 DataSourceBuilder 成功建立與數據源的連接?

完整的堆棧跟蹤:

2017-02-04 20:13:22.201 ERROR 12528 --- [           main] o.a.tomcat.jdbc.pool.ConnectionPool      : Unable to create initial connections of pool.

java.sql.SQLException: Unable to load class: com.mysql.jdbc.Driver from ClassLoader:sun.misc.Launcher$AppClassLoader@764c12b6;ClassLoader:sun.misc.Launcher$AppClassLoader@764c12b6
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:283) ~[tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:732) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:664) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:479) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.11.jar:na]
    at nl.mierasmade.driver.DriverLoader.loadDriver(DriverLoader.java:54) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_112]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_112]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_112]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) [spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) [spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) [spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at nl.mierasmade.JdbcRuntimeDriverApplication.main(JdbcRuntimeDriverApplication.java:10) [classes/:na]
Caused by: java.lang.ClassNotFoundException: Unable to load class: com.mysql.jdbc.Driver from ClassLoader:sun.misc.Launcher$AppClassLoader@764c12b6;ClassLoader:sun.misc.Launcher$AppClassLoader@764c12b6
    at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) ~[tomcat-jdbc-8.5.11.jar:na]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:271) ~[tomcat-jdbc-8.5.11.jar:na]
    ... 33 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_112]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112]
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_112]
    at java.lang.Class.forName0(Native Method) ~[na:1.8.0_112]
    at java.lang.Class.forName(Unknown Source) ~[na:1.8.0_112]
    at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38) ~[tomcat-jdbc-8.5.11.jar:na]
    ... 34 common frames omitted

我能夠像這樣開始工作:

  @Bean
  public DataSource dynamicDataSource() {
    ClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:///C:/Users/xxxx/Desktop/h2-1.4.193.jar")}, Thread.currentThread().getContextClassLoader());
    Thread.currentThread().setContextClassLoader(classLoader);
    DataSource dataSource = DataSourceBuilder.create().url('jdbc:h2:mem:test;DB_CLOSE_DELAY=-1').build();
    dataSource.getConnection().isValid(10);
    return dataSource;
  }

試試this.getClass().getClassLoader()Thread.getContextClassLoader()而不是使用系統的類加載器。 參考E.5.2 系統類加載器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM