Spring Boot Maven 插件 - 没有 BOOT-INF 目录
Posted
技术标签:
【中文标题】Spring Boot Maven 插件 - 没有 BOOT-INF 目录【英文标题】:Spring Boot Maven Plugin - No BOOT-INF directory 【发布时间】:2017-08-24 18:59:13 【问题描述】:在 spring-boot-maven-plugin 的 1.3.8.RELEASE 版本和 1.4.0.RELEASE 版本之间 - 生成的包结构发生了变化(如果您提取 uber jar 文件) 1.3.8.RELEASE com、lib、META-INF 和 org 目录 1.4.0.RELEASE 有 BOOT-INF、META-INF 和 org 目录 基本上从 1.4.0.RELEASE 开始——所有的类和库都在 BOOT-INF 目录中。 因此 - 当您尝试在 Amazon Lambda 上运行 Spring Boot 项目时 - 它说找不到 jar,因为它无法读取新的 Spring Boot Uber jar 结构
我的问题是 - 在较新版本的 Spring Boot Maven 插件中是否有可能让它生成与版本 1.3.9.RELEASE 相同的结构的 uber jar?
我尝试了 maven-shade-plugin - 但这会导致其他问题
非常感谢任何帮助
谢谢 达米安
【问题讨论】:
【参考方案1】:解决方案是在 pom.xml 文件中为插件添加 MODULE 布局
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>MODULE</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
【讨论】:
为什么没有人将其标记为正确答案。当我升级弹簧靴时,我遇到了类似的问题。对 docs.Spring 的描述感到困惑。添加这件作品。在我的情况下,我使用的是 spring boot 2.X,我在 maven-dependency-plugin
之后声明了 spring-boot-maven-plugin
(我曾经在 Docker 中解压并创建分解的应用程序),它必须在解压之前,这是有道理的,它在spring boot maven插件执行之前被解包。下次我将在插件链中声明它的第一件事,为此浪费了一个多小时。希望它可以帮助某人。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>$spring.boot.mainClass</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>$project.groupId</groupId>
<artifactId>$project.artifactId</artifactId>
<version>$project.version</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
【讨论】:
我还通过将我的 maven-shade-plugin 声明放在 pom.xml 中的 spring-boot-maven-plugin 声明之前,让我的设置正常工作。生成的 shade jar 按预期在根目录中包含所有内容,而 Spring boot jar 按预期在 BOOT-INF 中包含所有内容。【参考方案3】:上面的答案用
<layout>MODULE</layout>
不再起作用,这是因为 layout 元素在 Spring Boot 2.x 中已被弃用。 我正在使用 Spring Boot 2.0.x,我在 github 上发现了这条有用的评论:
在 Spring Boot 2.0 中删除了对模块布局的支持,在 1.5 中已弃用。不幸的是,Maven 插件文档的更新被遗漏了,所以我们可以使用这个问题来解决这个问题。您应该改用custom LayoutFactory。
但由于我不想实现 LayoutFactory,所以我尝试了下面的第二个解决方案,它实际上重新打包并创建了一个带有给定名称的分类器的额外 jar:
这是由于 Spring Boot 1.4 中可执行 jar 的布局发生了变化。应用程序类现在打包在 BOOT-INF/classes 中。 您的客户端模块依赖于重新打包的 web 模块的胖 jar。由于新布局意味着客户端模块无法再加载 Web 模块的类。如果你想使用你的 web 模块作为依赖,你应该配置 Boot 的重新打包以将分类器应用于 fat jar。例如:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
这样做将允许其他模块依赖于原始 jar,该 jar 没有嵌入模块的依赖项,并且在 jar 的根目录下具有类。
一个原始罐子的结构与我想要的一样
com.my-package.foo.bar
META-INF
第二个分类器具有更新的结构,带有 BOOT-INF/ 等。
【讨论】:
非常感谢。很好的回答【参考方案4】:对我来说,解决方案有点阴险......我将 spring-boot-maven-plugin 嵌套在 pluginManagement 下(见下文)。嗬!
令人讨厌的是,当我运行 mvn spring-boot:run 时,spring boot 运行良好,并运行 app!直到我们尝试部署到 PCF(作为 spring-boot JAR),我们才得到一个错误,表明二进制格式有问题....
<build>
<!--
DON'T DO THIS!!
-->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>$spring.boot.version</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<!--
DO THIS INSTEAD!!
-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>$spring.boot.version</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
从 POM 中删除 pluginManagement 标记后,我现在将获得 ./BOOT-INF 结构。请记住,pluginManagement 通常用于父 pom 结构,您希望该插件的配置在其他模块中使用。
【讨论】:
【参考方案5】:我使用的是 Gradle,而不是 Maven,这是我必须做的:
1- 在我的 build.gradle 中,我添加了 https://spring.io/guides/gs/spring-boot-Docker/ 中定义的以下属性。
buildscript
...
dependencies
...
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
group = 'springio'
...
apply plugin: 'com.palantir.docker'
task unpack(type: Copy)
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
docker
name "$project.group/$bootJar.baseName"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
2- 我的依赖文件夹没有被写入
ARG DEPENDENCY=target/dependency
相反,我将它放在另一个文件夹中,因此我在 Dockerfile 中更改了此属性:
ARG DEPENDENCY=build/dependency
这样我就成功构建了。
【讨论】:
以上是关于Spring Boot Maven 插件 - 没有 BOOT-INF 目录的主要内容,如果未能解决你的问题,请参考以下文章
Maven对原始Spring Boot JAR的依赖[重复]
Spring Boot Maven 插件 - spring-boot:run 和优雅关闭
找不到符号 - Spring Boot Maven 兄弟作为依赖
Maven插件系列之spring-boot-maven-plugin
使用 Spring Boot BOM 管理 Maven 插件版本
SpringBootPlugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found