Spring Boot 从命令行执行将文件添加到类路径

Posted

技术标签:

【中文标题】Spring Boot 从命令行执行将文件添加到类路径【英文标题】:Spring Boot add files to classpath from command line execution 【发布时间】:2017-11-23 13:30:00 【问题描述】:

我正在使用 Netbeans 8.2 开发 Spring 应用程序。我遇到问题的这个特定应用程序是 Spring Boot 1.5.3 应用程序。我有一个 spring xml 文件和一个 application.properties,我保存在根项目目录下的 /config 中。

我通过@ImportResource 注释和@ImportResource(value="$config.xmlfile") 之类的值属性将spring xml 文件传递​​给我的项目。

当我单击 Netbeans 中的“运行项目”按钮时,我的 Spring 应用程序会启动,它会在我的 /config 文件夹中正确找到 application.properties 文件。但是,对该文件夹中其他文件的任何类路径引用都将丢失。例如,将 config.xml 文件设置为 classpath:config/file.xmlclasspath:file.xml 均无法找到该文件,但 file:config/file.xml 有效。

同样,从命令行运行时,我的结构如下:

app/
|-- bin
|   `-- app-run.sh
|-- config
|   |-- application.properties
|   |-- log4j2.xml
|   |-- file.xml
`-- app-exec.jar

我正在使用spring-boot-maven-plugin 来制作罐子,如下所示:

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

我的 app-run.sh 脚本执行以下操作:

exec /bin/java -cp :.:../config/*:../app-exec.jar 
-Dlogging.config=../config/log4j2.xml 
-Dspring.config.location=../config/application.properties 
-jar ../app-exec.jar

/bin/java 代表我安装 java 的位置。 -cp 中设置的类路径似乎在这里不起作用。与通过 IDE 运行时类似,将 config.xml 文件设置为 classpath:config/file.xml 或 classpath:file.xml 都无法找到该文件,但 file:../config/file.xml 有效。

我希望能够在 IDE 和命令行中设置类路径,以便我可以使用类路径引用访问 Spring 中的文件,从而使事情变得更容易。我不想将它们全部放在src/main/resources 中并将它们打包在 jar 中,因为我需要在打包和部署后对其进行编辑。

有没有人有任何想法或有用的提示?提前致谢!

【问题讨论】:

【参考方案1】:

更新答案:

您可以按照我原来的答案中的做法进行操作,但我们最近放弃了这一做法,以获得更标准的更简单、更清洁的选项(“Java”方式)。我们进行更改是因为我们需要在运行时动态加载编译时不可用的依赖库(在它们的确切版本中)。在我们的例子中,我们只想从单独的文件夹而不是从可执行 jar 加载依赖 jar。我们最终在可执行 jar 和单独的文件夹中存在重复的依赖项,因此我们决定删除可执行 jar 属性启动器,而只从单独的文件夹加载依赖项。这通常不是最佳选择,应针对您的用例进行评估。我更喜欢阅读标准的 Java 类路径。

为了在没有可执行 jar 的情况下运行 Spring Boot 应用程序,我们使用 Maven Assembly 将依赖的 jar 放在 /libs 目录中,并删除了 spring-boot-maven-plugin。步骤和一些代码如下:

    删除以 ZIP 格式创建可执行 jar 的 spring-boot-maven-plugin

    将以下内容添加到您的程序集 XML

    <dependencySets> <dependencySet> <outputDirectory>where you want the libs to go</outputDirectory> <useProjectArtifact>whether you want to include the project artifact here</useProjectArtifact> </dependencySet> </dependencySets>

    从主类运行您的代码,并在类路径中包含相关的 jar 文件夹。在您的操作系统上使用标准的类路径表示法,而不是使用自定义的、笨拙的 PropertiesLauncher 加载器路径语法

    java -cp &lt;standard-classpath&gt; &lt;main-class&gt;

一个实际调用的例子: java -cp $CLASSPATH:./lib/*:./cfg/*:my-app.jar Application.class

通过这种方式,您可以通过标准的 java 执行调用来执行 Spring Boot 应用程序,无需自定义 Spring 加载语法。您只需要确保所有依赖项在运行时在类路径上可用。我们发现这更容易维护,并将其作为我们所有应用的标准。

原答案:

经过一些研究,感谢@TuyenNguyen 的有用回答,我得以完成以下工作:

我在 spring-boot-maven-plugin 中添加了以下内容,这样当我从命令行运行时,它使用 PropertiesLauncher 而不是 JarLauncher

<configuration>
     <mainClass>$mainClass</mainClass>
     <layout>ZIP</layout> //THIS IS THE IMPORTANT PART
</configuration>

有关PropertiesLauncher 选项的更多信息,请参阅here 和here。它允许您设置类路径等。 请参阅here、here 和here,了解我在哪里找到了这个问题的答案。使用 ZIP 格式可以使用 PropertiesLauncher

从那里,我能够使用此命令按预期启动应用程序:

java -Dloader.path=../config,../ -Dloader.config.location=classpath:application.properties -jar ../app-exec.jar

另一个重要注意事项:指定-Dloader.path 时,请确保使用逗号分隔的值并且仅使用目录和文件,如here 所述。另外,请务必在指定 -jar jar 之前放置 -D 参数,否则将不会设置它们。

如果有人有任何建议或编辑以进一步改进此答案或原始问题以帮助其他用户,请告诉我或自己进行编辑!

【讨论】:

感谢您的详细说明。我在命令中更改 -Dloader.path 的位置后它就可以工作了。 @Silentbang 很高兴这个答案有所帮助,我花了一些时间来弄清楚事情。 Spring 中关于这个主题领域的文档很不错,但在某些地方打破了惯例,例如如何在传递给 -Dloader.path 时指定路径【参考方案2】:

如果您不将文件放在src/main/resources 中,那么您可以将其放在您想要的任何文件夹中,但您必须将您的文件夹设置为资源文件夹。因为classpath 总是指向资源文件夹。一旦您将文件夹作为资源文件夹,它将被打包到 jar 中。如果你想编辑你的资源文件,只需使用7 zip tool 打开你的 jar -> 编辑文件 -> 保存 -> 它将更新你在 jar 中的更改。

另一种解决方法是创建一个文件夹,把所有你想编辑的文件都放在里面,没有打包,然后每次运行时手动设置classpath到那个文件夹,但是你上面设置的方式不正确,试试this解决方案设置类路径的正确方法。

【讨论】:

谢谢,您提供的第二个选项看起来是合适的解决方案。但是,鉴于这是一个重新打包的 Spring Boot 应用程序,我无法轻松访问 jar 的内部类。我的 main() 类已被重新打包,因此我无法像第二个示例中那样访问它。我要看看我是否可以使用PropertiesLauncher 记录的here

以上是关于Spring Boot 从命令行执行将文件添加到类路径的主要内容,如果未能解决你的问题,请参考以下文章

用Spring Boot开发命令行执行程序

从命令行启动应用程序时,如何将 Spring Boot 应用程序 jar 中的文件作为 -D 属性值引用?

Spring Boot配置文件放在jar外部

Spring Boot配置文件放在jar外部

Spring Boot,即使正在执行删除命令,对象也不会被删除

在 Spring Boot 中从命令行设置活动配置文件和配置位置