我有一个Spring Boot应用程序,允许从类路径加载其他组件(如果它们是我的应用程序中定义的接口的子类)。这在Spring Boot 1.3.8中运行得很好,但是我想升级到Spring Boot 1.4.2,但是new layout of executable JARs导致了一些问题。
当我现在在类路径上使用额外的JAR运行我的应用程序时,我得到了一个ClassNotFoundException,用于我正在尝试子类化的接口。这告诉我,尽管应用程序知道我的类在BOOT-INF中的位置,但由于它们不在标准位置,因此其他组件无法找到它们。
有谁知道如何解决这个问题?
我在spring-boot-maven-plugin中尝试了不同的布局选项,但它们似乎都没有做我想要的。
答案 0 :(得分:9)
Spring Boot可执行jar在运行时使用自己的ClassLoader created by a Launcher。由System ClassLoader加载的类(由-cp
类路径指定)不知道可执行jar中由子ClassLoader加载的类。因此,在你的情况下ClassNotFoundException。
JAR
或WAR
布局中的可执行jar使用简单的Launcher
只关心捆绑包中的类。您必须使用PropertiesLauncher
指示Spring Boot的ClassLoader通过以任一方式指定loader.path
应用程序属性来加载您的类:
$ java -Dloader.path=... -cp myjar.jar org.springframework.boot.loader.PropertiesLauncher [args...]
此命令绕过可执行jar / war中的默认Luncher(在 myjar.jar!/META-INF/MANIFEST.MF 中的Main-Class
条目中列出)。并直接调用PropertiesLauncher
类。
ZIP
布局)ZIP 布局,如Spring Boot documentation:
中所述与 JAR 布局类似,使用
PropertiesLauncher
。
布局中的打包可执行文件默认会查找loader.*
属性,因此您可以像以下一样运行它:
$ java -Dloader.path=... -jar myjar.jar [args...]
对于Maven项目,在POM.xml中将布局设置为ZIP:
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
</configuration>
</plugin>
</plugins>
</build>
</project>
对于Gradle项目:
springBoot {
layout = 'ZIP'
}