SpringBoot loader.path 无法加载外部Jar

Posted

技术标签:

【中文标题】SpringBoot loader.path 无法加载外部Jar【英文标题】:SpringBoot loader.path Unable to load external Jar 【发布时间】:2016-08-23 15:23:22 【问题描述】:

我正在为 webapp 使用 springboot,并且我正在尝试设置一个外部目录,该目录将保存最终用户可能选择使用的各种 JDBC 驱动程序。为此,我要添加:

loader.path=/opt/myapp/lib/

到我的 application.properties 文件,这是由 PropertySourcesPropertyResolver 拾取的

2016-04-28 17:27:38.739 DEBUG 22539 --- [restartedMain] o.s.c.e.PropertySourcesPropertyResolver  : Found key 'loader.path' in [applicationConfigurationProperties] with type [String] and value '/opt/myapp/lib/'

我的问题是我似乎无法从放入此目录的任何 jar 中加载任何 JDBC 驱动程序,我缺少什么?我正在使用默认的嵌入式 tomcat 服务器。当我尝试使用 Class.forName 加载驱动程序时,我得到以下信息,就像该目录中不存在罐子一样。

 public Connection buildConnection(DataSource dataSource) throws ClassNotFoundException, SQLException 

    if (dataSource == null) 
        throw new NullPointerException("Data Source is null!");
    

    if (!dataSource.isReady()) 
        throw new IllegalArgumentException("Data Source is reporting that it is not ready!");
    

    logger.debug("Loading JDBC Driver: ", dataSource.getDriverClass());
    Class.forName(dataSource.getDriverClass());
    logger.debug("Loaded Driver: ", dataSource.getDriverClass());

    logger.debug("Attempting to build connection using: ", dataSource.getConnectionString());

    DriverManager.setLoginTimeout(10);
    Connection c = DriverManager.getConnection(dataSource.getConnectionString(), dataSource.getUserName(), dataSource.getPassword());
    if (c != null) 
        c.setAutoCommit(true);
        c.setReadOnly(true);
        return c;
    
    throw new NullPointerException("Unable to create connection!");
 

这是抛出的异常

2016-04-28 17:38:53.525 DEBUG 22539 --- [nio-8081-exec-5] c.c.reportout.processor.JobProcessor     : Loading JDBC Driver: com.mysql.jdbc.Driver
2016-04-28 17:38:53.526  WARN 22539 --- [nio-8081-exec-5] c.c.reportout.processor.JobProcessor     : Unable to successfully test connection: com.mysql.jdbc.Driver

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_91]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_91]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_91]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_91]
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:151) ~[spring-boot-devtools-1.3.3.RELEASE.jar:1.3.3.RELEASE]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_91]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_91]
at java.lang.Class.forName(Class.java:264) ~[na:1.8.0_91]

关于如何调试或我做错了什么的任何指示?

谢谢

【问题讨论】:

您是如何构建和打包您的应用程序的? loader.path 仅在您使用 PropertiesLauncher 时有效。 是的,我做到了。我刚刚构建了 jar 并使用 java -jar MyApp-1.0-SNAPSHOT.jar 运行它,我得到了相同的结果。 如果我将 jdbc 驱动程序依赖项添加到我的 pom 中,它显然可以工作,但由于某种原因我无法从外部目录加载它。 【参考方案1】:

所以经过多次谷歌搜索,事实证明我能够通过添加以下内容来解决它:

<configuration>
    <layout>ZIP</layout>
</configuration>

到我的 pom 文件中的 spring-boot-maven-plugin 插件。所以工作版本现在看起来像这样:

<plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>$spring-boot.version</version>
            <configuration>
                <layout>ZIP</layout>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

【讨论】:

如果它对任何人都有帮助,据我所知,这只会告诉 Spring Boot 在运行可执行 jar 时使用 PropertiesLauncher,而不是在使用 mvn spring-boot:run 时使用 附加说明:生成fully executable jar(通过同时添加&lt;executable&gt;true&lt;/executable&gt;&lt;layout&gt;ZIP&lt;/layout&gt;)我必须使用环境变量LOADER_PATH 而不是loader.path 属性。

以上是关于SpringBoot loader.path 无法加载外部Jar的主要内容,如果未能解决你的问题,请参考以下文章

springboot无法启动

解决IDEA无法识别SpringBoot项目

springboot错误: 找不到或无法加载主类

SpringBoot:无法与maven创建战争:无法找到主类

springboot zip文件上传无法解压

springBoot和MyBatis整合中出现SpringBoot无法启动时处理方式