Spring Boot可执行JAR - 布局更改中断了Classpath

时间:2016-12-06 11:58:03

标签: java spring-boot

我有一个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中尝试了不同的布局选项,但它们似乎都没有做我想要的。

1 个答案:

答案 0 :(得分:9)

Spring Boot可执行jar在运行时使用自己的ClassLoader created by a Launcher。由System ClassLoader加载的类(由-cp类路径指定)不知道可执行jar中由子ClassLoader加载的类。因此,在你的情况下ClassNotFoundException。

JARWAR布局中的可执行jar使用简单的Launcher只关心捆绑包中的类。您必须使用PropertiesLauncher指示Spring Boot的ClassLoader通过以任一方式指定loader.path应用程序属性来加载您的类:

方法1.直接运行PropertiesLauncher类:

$ java -Dloader.path=... -cp myjar.jar org.springframework.boot.loader.PropertiesLauncher [args...]

此命令绕过可执行jar / war中的默认Luncher(在 myjar.jar!/META-INF/MANIFEST.MF 中的Main-Class条目中列出)。并直接调用PropertiesLauncher类。

方法2.将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'
}