【问题标题】:Spring Boot Executable JAR - Layout Changes break ClasspathSpring Boot Executable JAR - 布局更改中断类路径
【发布时间】:2016-12-06 11:58:03
【问题描述】:

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

【问题讨论】:

  • 通过loader.path应用程序属性而不是JVM选项-cp设置类路径。
  • 我已经尝试过了,但是组件扫描似乎没有拾取附加 JAR 中的组件(我无法判断组件是否可以找到接口,因为它们不是被捡起来检查!)。我尝试在命令行 (-Dloader.path=...) 和 application.properties 上设置它,但在这两种情况下它都没有选择我的其他组件。
  • 您是否以正确的格式设置了loader.path?它是一个逗号分隔的列表,不像 java -cp 使用 : 或 ; 作为取决于操作系统的分隔符。
  • 是的,我尝试了一个 JAR,其路径相对于我正在运行的目录。
  • 对不起,您必须明确指定ProperitesLauncher 才能生效。尝试将命令从java -Dloader.path=... -jar myjar.jar 更改为java -Dloader.path=xxx -Dloader.debug=true -cp myjar.jar org.springframework.boot.loader.PropertiesLauncher。

标签: java spring-boot


【解决方案1】:

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

JAR 或WAR 布局中的可执行jar 使用简单的Launchers 只关心打包在包中的类。您必须使用PropertiesLauncher 来指示Spring Boot 的ClassLoader 通过指定loader.path 应用程序属性来加载您的类:

方法一、直接运行PropertiesLauncher类:

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

此命令绕过可执行 jar/war 中的默认午餐器(列在 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'
}

【讨论】:

  • 附加说明:生成fully executable jar(通过同时添加&lt;executable&gt;true&lt;/executable&gt; 和&lt;layout&gt;ZIP&lt;/layout&gt;)我必须使用环境变量LOADER_PATH 而不是loader.path 属性。
猜你喜欢
  • 2015-01-14
  • 2016-03-13
  • 2017-02-04
  • 1970-01-01
  • 2017-08-07
  • 2018-08-17
  • 2018-05-23
  • 2018-09-20
相关资源
最近更新 更多