【问题标题】:Spring Boot Executable Jar with Classpath带有类路径的 Spring Boot 可执行 Jar
【发布时间】:2017-02-04 14:54:27
【问题描述】:

我正在使用 Spring Boot 构建一个与企业软件系统交互的软件系统。我的系统依赖于该企业系统中的一些 jar 和 *.ini 文件,因此我无法在 Maven 中打包所有依赖项。我希望能够将 Spring Boot 作为带有嵌入式 Tomcat 的可执行 Jar 运行。我还希望能够通过命令行设置类路径。所以像:

java -classpath /home/sleeper/thirdparty/lib -jar MyApp.jar

但是,-classpath 和 -jar 不能共存。我试过“-Dloader.path”。它能够加载文件夹下的所有jar文件,但不能加载其他东西,如文件夹中的*.ini文件。

那么有没有一种方法可以让 -classpath 与嵌入了 Tomcat 的 Spring 可执行 jar 一起工作?

【问题讨论】:

标签: java spring spring-boot


【解决方案1】:

对我有用的一个解决方案是将带有外部类的 jar 插入到 MANIFEST.MFClass-Path 中。这是因为-jar 开关忽略了-classpath 选项和CLASSPATH 环境变量。
程序:

  1. maven-jar-plugin 安装到 POM 中;
  2. 添加行:
    <configuration>
        <archive>
            <manifestEntries>
                <Class-Path>/my/external/jar/absolute/path.jar</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>

使用java -jar myapp.jar 构建和运行。它的清单将包含以下行:

Class-Path: /my/external/jar/absolute/path.jar

这样外部 jar 将在运行时而不是在编译时被搜索(它不会被复制到 BOOT_INF/lib)。

来源:

post 1

post 2

【讨论】:

    【解决方案2】:

    在 Spring Boot 项目中添加依赖项的标准方法是将这些 Jar 文件放入 BOOT-INF/lib。这将导致在生成的jarwar 文件中复制该依赖项,并更新classpath.idx

    可以看官方文档here

    准确性文献说:

    应用程序类应放置在嵌套的 BOOT-INF/classes 目录中。依赖项应该放在嵌套的 BOOT-INF/lib 目录中

    我已经使用外部 Jar 文件执行此操作,一切正常。

    【讨论】:

      【解决方案3】:

      只是添加一个没有 PropertiesLauncher 或太多参数的简单解决方案。

      1 - 构建您的标准可执行 springboot jar (my-spring-boot-app.jar)

      2 - 然后在不使用 -jar 选项并使用 JarLauncher 类作为主类的情况下运行它

      java -cp "/path/to/jars/*:/path/to/app/my-spring-boot-app.jar" org.springframework.boot.loader.JarLauncher
      

      (相对路径也完全有效)

      就是这样

      【讨论】:

      • 这也适用于 org.springframework.batch.core.launch.support.CommandLineJobRunner 作为清单中声明的​​主类。
      【解决方案4】:

      如果您只想添加外部库,可以使用loader.path 属性。

      java -Dloader.path="your-lib/" -jar your-app.jar
      

      更新

      如果您还需要从类路径中读取其他文件,则必须创建/更改应用程序的清单文件。

      假设您正在从 de.app.Application 类初始化 Spring Boot 上下文。您的 MANIFEST.MF 应如下所示:

      Manifest-Version: 1.0
      Main-Class: de.app.Application
      Class-Path: your-lib/
      

      您可以简单地使用java -Dloader.path="your-lib/" -jar MyApp.jar 启动您的应用程序。

      有关 MANIFEST.MF 的更多信息,请参阅Working with Manifest Files: The Basics

      【讨论】:

      • 我实际上已经尝试过了。请参阅我原来的问题。它与 -classpath 的工作方式不同。它加载 jar 文件,但不加载 ini 文件。
      • @user1670498,抱歉我忽略了这一点。有关新的详细信息,请参阅我的回答。
      • 其实它适用于非jar文件,但不适用于jar文件。所以我的应用程序可以从类路径中读取 /home/sleeper/thirdparty/lib/ 中的任何 ini 文件,但它无法从 /home/sleeper/thirdparty/lib/ 加载任何 jar 文件。
      • 经过大量研究,似乎“Class-Path:/home/sleeper/thirdparty/lib/”不会加载文件夹下的任何jar文件。要引用 jar 文件,我们需要明确引用每个单独的 jar,例如“Class-Path: /home/sleeper/thirdparty/lib/abc.jar /home/sleeper/thirdparty/lib/def.jar”。跨度>
      • 我实际上阅读了该博客,并且我的类路径以“/”结尾。我想博客说的是,它不会加载目录中的jar文件,而是会加载目录中的.class文件。
      【解决方案5】:
        java -cp  C:\jar-path\your-jar-1.2.0.jar -Dloader.main=package-and-main class  -Dloader.path=external dependency jar path  org.springframework.boot.loader.PropertiesLauncher -Dspring.profiles.active=profile etc -default,test --spring.config.location=external properties file name
      

      如果要定义外部存储器使用

              java -ms8g -mx8g -cp
      

      java -cp

      -Dloader.main

      Spring Boot 的 org.springframework.boot.loader.PropertiesLauncher 带有一个 JVM 参数,可以让您覆盖名为 loader.main 的逻辑主类:

      -Dloader.path

      告诉 PropertiesLauncher 它应该选择在“lib”中找到的所有库

      org.springframework.boot.loader.PropertiesLauncher

      Spring Boot 的 org.springframework.boot.loader.PropertiesLauncher 带有一个 JVM 参数,可以让您覆盖名为 loader.main 的逻辑主类:

                java -cp bootApp.jar -Dloader.main=org.khan.DemoApplication  org.springframework.boot.loader.PropertiesLauncher
      

      -Dspring.profiles.active

      如果你使用的是 Spring profile 那么你需要先设置 profile

           set SPRING_PROFILES_ACTIVE=default,test
      

      或窗口运行输入env并添加

            spring_profiles_active
             default,test
      

      --spring.config.location

      指定目录然后搜索application.properties

      【讨论】:

        【解决方案6】:

        在 Linux 上:

        java -cp MyApp.jar:/home/sleeper/thirdparty/lib -Dloader.main=myMainApplicationClass org.springframework.boot.loader.PropertiesLauncher
        

        在 Windows 上:

        java -cp MyApp.jar;/home/sleeper/thirdparty/lib -Dloader.main=myMainApplicationClass org.springframework.boot.loader.PropertiesLauncher
        

        这将避免与其他答案中的清单或 Spring Boot Maven 插件配置混淆。它将使用 PropertiesLauncher 启动您的应用程序,它允许您在 loader.main 中指定主类。 如前所述,由于某种原因,如果您将 PropertiesLauncher 与 loader.path 一起使用,它不会将资源文件添加到类路径中。这可以通过使用 -cp 而不是 -jar 来解决此问题。

        编辑 正如Pianosaurus在评论中提到的,使用“:”而不是“;”在 Linux 上作为类路径中的分隔符

        【讨论】:

        • 谢谢,这对我们有用。如果您在 un*x 上,请记住在类路径中使用“:”作为分隔符。
        • 这个解决方案支持在启动时从类路径读取配置文件,所以这对我的小型 spring-boot 应用程序来说是一个胜利。这应该是公认的答案。
        • 记得为-Dloader.main使用类的完全限定名
        【解决方案7】:

        您提到您需要从外部文件夹加载 *.ini 文件。我必须做类似的事情,从外部文件夹加载 CSV 文件。

        我的文件结构是这样的

        ./myapp.jar  
        ./config/file.csv
        

        我使用 ResouceLoader 将文件加载为:

        Resource res = resourceLoader.getResource("classpath:file.csv");
        File csvFile = res.getFile();
        

        启动脚本:

        java -Dloader.path="config" -jar your-app.jar
        

        资源未按预期从“config”文件夹加载。经过一番研究,我发现我必须更改我的 Maven 插件配置才能使用 ZIP 布局。

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <layout>ZIP</layout>
            </configuration>
        </plugin>
        

        这将引导 Spring Boot 使用 PropertiesLauncher,它允许从“loader.path”加载外部资源。

        查看这个优秀的article 了解更多详情。

        【讨论】:

          猜你喜欢
          • 2021-01-10
          • 1970-01-01
          • 2018-05-26
          • 1970-01-01
          • 2014-12-18
          • 1970-01-01
          • 1970-01-01
          • 2017-11-21
          • 2017-01-20
          相关资源
          最近更新 更多