Build
Spring Boot 包含了用于 Maven 和 Gradle 的构建插件。本节回答有关这些插件的常见问题。
生成构建信息
Maven 插件和 Gradle 插件均支持生成包含项目坐标、名称和版本的构建信息。这些插件还可以通过配置添加额外的属性。当存在此类文件时,Spring Boot 会自动配置一个 BuildProperties Bean。
要使用 Maven 生成构建信息,请为 build-info 目标添加一个 execution,如下例所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.5.10</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
更多详情请参阅 Spring Boot Maven Plugin 文档。
以下示例使用 Gradle 实现相同的功能:
springBoot {
buildInfo()
}
更多详情请参见 Spring Boot Gradle Plugin 文档。
生成 Git 信息
Maven 和 Gradle 都允许生成一个 git.properties 文件,其中包含项目构建时 git 源代码仓库的状态信息。
对于 Maven 用户,spring-boot-starter-parent POM 中包含了一个预配置的插件,用于生成 git.properties 文件。要使用它,请将以下 Git Commit Id Plugin 的声明添加到你的 POM 中:
<build>
<plugins>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Gradle 用户可以通过使用 gradle-git-properties 插件来实现相同的效果,如下例所示:
plugins {
id "com.gorylenko.gradle-git-properties" version "2.4.1"
}
Maven 和 Gradle 插件都允许配置包含在 git.properties 中的属性。
git.properties 中的提交时间应符合以下格式:yyyy-MM-dd’T’HH:mm:ssZ。这是上述两个插件的默认格式。使用此格式可使时间被解析为 Date,并且在序列化为 JSON 时,其格式可通过 Jackson 的日期序列化配置进行控制。
生成 CycloneDX SBOM
Maven 和 Gradle 都允许在项目构建时生成 CycloneDX SBOM。
对于 Maven 用户,spring-boot-starter-parent POM 中包含了一个预配置的插件用于生成 SBOM。要使用它,请在你的 POM 中添加以下 cyclonedx-maven-plugin 的声明:
<build>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Gradle 用户可以通过使用 cyclonedx-gradle-plugin 插件来实现相同的结果,如下例所示:
plugins {
id 'org.cyclonedx.bom' version '2.3.0'
}
自定义依赖版本
spring-boot-dependencies POM 管理常用依赖项的版本。Maven 和 Gradle 的 Spring Boot 插件允许使用构建属性来自定义这些受管理的依赖版本。
每个 Spring Boot 版本都是针对这一特定的第三方依赖集进行设计和测试的。覆盖版本可能会导致兼容性问题。
要使用 Maven 覆盖依赖版本,请参阅 Maven 插件文档中的 Using the Plugin。
要覆盖 Gradle 中的依赖版本,请参阅 Gradle 插件文档中的 自定义托管版本。
使用 Maven 创建可执行 JAR
spring-boot-maven-plugin 可用于创建可执行的 “fat” JAR。如果你使用了 spring-boot-starter-parent POM,可以声明该插件,你的 JAR 将按如下方式重新打包:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果你不使用父 POM,你仍然可以使用该插件。但是,你必须额外添加一个 <executions> 部分,如下所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.5.10</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
完整的使用详情请参见 插件文档。
将 Spring Boot 应用程序用作依赖项
与 WAR 文件类似,Spring Boot 应用程序并不适合作为依赖项使用。如果你的应用程序包含希望与其他项目共享的类,推荐的做法是将这些代码移到一个独立的模块中。该独立模块随后可以被你的应用程序以及其他项目所依赖。
如果你无法按照上述建议重新组织代码,那么必须配置 Spring Boot 的 Maven 和 Gradle 插件,以生成一个单独的、适合作为依赖项使用的构件。可执行归档文件不能用作依赖项,因为 可执行 jar 格式 将应用程序类打包在 BOOT-INF/classes 中。这意味着当可执行 jar 被用作依赖项时,这些类将无法被找到。
要生成两个构件(一个用作依赖项,另一个可执行),必须指定一个 classifier。该 classifier 会应用到可执行归档文件的名称上,而默认的归档文件则保留用于依赖项。
要配置 Maven 中 exec 的 classifier,可以使用以下配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
在可执行 Jar 运行时提取特定库
可执行 jar 中的大多数嵌套库无需解压即可运行。然而,某些库可能会出现问题。例如,JRuby 自带了对嵌套 jar 的支持,它假设 jruby-complete.jar 始终可以直接作为一个独立的文件使用。
为处理任何有问题的库,你可以标记特定的嵌套 JAR,在可执行 JAR 首次运行时自动解包。这些嵌套 JAR 会被写入到由 java.io.tmpdir 系统属性指定的临时目录下。
应注意确保您的操作系统已正确配置,以免在应用程序仍在运行时删除已解压到临时目录的 JAR 文件。
例如,若要通过 Maven Plugin 标记 JRuby 以进行解包,您应添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
创建一个不可执行的 JAR 并排除某些内容
通常,如果你有一个可执行 JAR 和一个不可执行 JAR 作为两个独立的构建产物,那么可执行版本会包含一些在库 JAR 中不需要的额外配置文件。例如,application.yaml 配置文件可能会从不可执行 JAR 中排除。
在 Maven 中,可执行的 JAR 必须是主构件(main artifact),你可以为库添加一个分类器(classifier)的 JAR,如下所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>lib</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>lib</classifier>
<excludes>
<exclude>application.yaml</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
使用 Maven 启动的 Spring Boot 应用程序进行远程调试
要将远程调试器附加到通过 Maven 启动的 Spring Boot 应用程序,可以使用 maven 插件 的 jvmArguments 属性。
更多详情请参见 此示例。
使用 Ant 构建可执行归档文件而不使用 spring-boot-antlib
要使用 Ant 进行构建,你需要获取依赖项、编译,然后创建一个 jar 或 war 归档文件。要使其可执行,你可以使用 spring-boot-antlib 模块,或者按照以下说明操作:
-
如果你正在构建一个 JAR,将应用程序的类和资源打包到嵌套的
BOOT-INF/classes目录中。如果你正在构建一个 WAR,则像往常一样将应用程序的类打包到嵌套的WEB-INF/classes目录中。 -
对于 JAR,将运行时依赖项添加到嵌套的
BOOT-INF/lib目录中;对于 WAR,则添加到WEB-INF/lib目录中。记住不要压缩归档文件中的条目。 -
对于 JAR,将
provided(嵌入式容器)依赖项添加到嵌套的BOOT-INF/lib目录中;对于 WAR,则添加到WEB-INF/lib-provided目录中。记住不要压缩归档文件中的条目。 -
将
spring-boot-loader的类放在归档文件的根目录下(以便Main-Class可用)。 -
在清单(manifest)中使用适当的启动器(例如 JAR 文件使用 JarLauncher)作为
Main-Class属性,并通过清单条目指定其所需的其他属性——主要是设置Start-Class属性。
以下示例展示了如何使用 Ant 构建一个可执行的归档文件:
<target name="build" depends="compile">
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
<mappedresources>
<fileset dir="target/classes" />
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="src/main/resources" erroronmissingdir="false"/>
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="${lib.dir}/runtime" />
<globmapper from="*" to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.launch.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>
</target>