打包可执行归档
该插件可以创建可执行的归档文件(jar 文件和 war 文件),这些文件包含应用程序的所有依赖项,然后可以使用 java -jar 运行。
打包可执行归档文件由 repackage 目标执行,如以下示例所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
repackage 目标不应单独在命令行上使用,因为它操作由 package 阶段生成的源 jar(或 war)。要在命令行上使用此目标,您必须包含 package 阶段:mvn package spring-boot:repackage。 |
如果您正在使用 spring-boot-starter-parent,则此执行已通过 repackage 执行 ID 预先配置,因此只需添加插件定义。 |
上面的示例重新打包了在 Maven 生命周期打包阶段构建的 jar 或 war 归档文件,包括项目中定义的任何 provided 依赖项。如果需要排除其中一些依赖项,可以使用其中一个 exclude 选项;有关详细信息,请参阅依赖项排除。
原始(即不可执行)工件默认重命名为 .original,但也可以使用自定义分类器保留原始工件。
maven-war-plugin 的 outputFileNameMapping 功能目前不受支持。 |
spring-boot-devtools 和 spring-boot-docker-compose 模块默认情况下会自动排除(您可以使用 excludeDevtools 和 excludeDockerCompose 属性控制此行为)。为了使其与 war 打包一起使用,spring-boot-devtools 和 spring-boot-docker-compose 依赖项必须设置为 optional 或 provided 范围。
该插件会重写您的清单文件,特别是它会管理 Main-Class 和 Start-Class 条目。如果默认值不起作用,您必须在 Spring Boot 插件中配置这些值,而不是在 jar 插件中。清单文件中的 Main-Class 由 Spring Boot 插件的 layout 属性控制,如以下示例所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start.class}</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
layout 属性默认为由归档类型(jar 或 war)决定的值。以下布局可用:
-
JAR:常规可执行 JAR 布局。 -
WAR:可执行 WAR 布局。provided依赖项放置在WEB-INF/lib-provided中,以避免在war部署到 Servlet 容器时发生冲突。 -
ZIP(别名DIR):类似于使用PropertiesLauncher的JAR布局。 -
NONE:捆绑所有依赖项和项目资源。不捆绑引导加载程序。
分层 Jar 或 War
重新打包的 jar 分别在 BOOT-INF/classes 和 BOOT-INF/lib 中包含应用程序的类和依赖项。类似地,可执行 war 在 WEB-INF/classes 中包含应用程序的类,在 WEB-INF/lib 和 WEB-INF/lib-provided 中包含依赖项。对于需要从 jar 或 war 的内容构建 docker 镜像的情况,能够进一步分离这些目录以便将它们写入不同的层是很有用的。
分层归档文件使用与常规重新打包的 jar 或 war 相同的布局,但包含一个描述每个层的附加元数据文件。
默认情况下,定义了以下层:
-
dependencies用于版本不包含SNAPSHOT的任何依赖项。 -
spring-boot-loader用于加载器类。 -
snapshot-dependencies用于版本包含SNAPSHOT的任何依赖项。 -
application用于本地模块依赖项、应用程序类和资源。
模块依赖项通过查看当前构建中的所有模块来识别。如果模块依赖项只能通过将其安装到 Maven 的本地缓存中来解决,并且它不是当前构建的一部分,则它将被识别为常规依赖项。
层的顺序很重要,因为它决定了当应用程序的一部分更改时,先前层被缓存的可能性。默认顺序是 dependencies、spring-boot-loader、snapshot-dependencies、application。最不可能更改的内容应首先添加,然后是更可能更改的层。
重新打包的归档文件默认包含 layers.idx 文件。要禁用此功能,您可以按以下方式操作:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>false</enabled>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
自定义层配置
根据您的应用程序,您可能希望调整层的创建方式并添加新层。这可以通过单独的配置文件完成,该文件应按如下所示注册:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
<configuration>${project.basedir}/src/layers.xml</configuration>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件描述了如何将归档文件分成层以及这些层的顺序。以下示例显示了如何明确定义上述默认顺序:
<layers xmlns="http://www.springframework.org/schema/boot/layers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
https://www.springframework.org/schema/boot/layers/layers-4.0.xsd">
<application>
<into layer="spring-boot-loader">
<include>org/springframework/boot/loader/**</include>
</into>
<into layer="application" />
</application>
<dependencies>
<into layer="application">
<includeModuleDependencies />
</into>
<into layer="snapshot-dependencies">
<include>*:*:*SNAPSHOT</include>
</into>
<into layer="dependencies" />
</dependencies>
<layerOrder>
<layer>dependencies</layer>
<layer>spring-boot-loader</layer>
<layer>snapshot-dependencies</layer>
<layer>application</layer>
</layerOrder>
</layers>
layers XML 格式定义为三个部分:
-
<application>块定义了应用程序类和资源应如何分层。 -
<dependencies>块定义了依赖项应如何分层。 -
<layerOrder>块定义了层的写入顺序。
嵌套的 <into> 块在 <application> 和 <dependencies> 部分中使用,用于声明层的内容。块按照它们定义的顺序从上到下进行评估。任何未被早期块声明的内容仍可供后续块考虑。
<into> 块使用嵌套的 <include> 和 <exclude> 元素来声明内容。<application> 部分使用 Ant 风格的路径匹配进行包含/排除表达式。<dependencies> 部分使用 group:artifact[:version] 模式。它还提供 <includeModuleDependencies /> 和 <excludeModuleDependencies /> 元素,可用于包含或排除本地模块依赖项。
如果未定义 <include>,则所有内容(未被早期块声明的内容)都将被考虑。
如果未定义 <exclude>,则不应用任何排除。
查看上面的 <dependencies> 示例,我们可以看到第一个 <into> 将为 application.layer 声明所有模块依赖项。下一个 <into> 将为 snapshot-dependencies 层声明所有 SNAPSHOT 依赖项。最后一个 <into> 将为 dependencies 层声明剩余的所有内容(在这种情况下,任何不是 SNAPSHOT 的依赖项)。
<application> 块具有相似的规则。首先为 spring-boot-loader 层声明 org/springframework/boot/loader/** 内容。然后为 application 层声明任何剩余的类和资源。
<into> 块的定义顺序通常与层的写入顺序不同。因此,<layerOrder> 元素必须始终包含,并且必须覆盖 <into> 块引用的所有层。 |
spring-boot:repackage
org.springframework.boot:spring-boot-maven-plugin:4.0.0
重新打包现有的 JAR 和 WAR 归档文件,以便它们可以使用 java -jar 从命令行执行。使用 layout=NONE 也可以简单地用于打包带有嵌套依赖项(且没有主类,因此不可执行)的 JAR。
可选参数
| 名称 | 类型 | 默认值 |
|---|---|---|
|
|
|
|
||
|
|
|
|
|
|
|
||
|
||
|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
|
|
||
|
|
参数详情
attach
将重新打包的归档文件附加到本地 Maven 仓库中安装或部署到远程仓库。如果未配置分类器,它将替换正常的 jar。如果已配置分类器,使得正常的 jar 和重新打包的 jar 不同,它将与正常的 jar 一起附加。当属性设置为 false 时,重新打包的归档文件将不会被安装或部署。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
classifier
添加到重新打包归档文件的分类器。如果未给出,则主工件将被重新打包的归档文件替换。如果给出,分类器还将用于确定要重新打包的源归档文件:如果已存在具有该分类器的工件,它将被用作源并替换。如果不存在此类工件,则主工件将用作源,重新打包的归档文件将作为带有该分类器的补充工件附加。附加工件允许将其与原始工件一起部署,有关详细信息,请参阅 Maven 文档。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeDevtools
从重新打包的归档文件中排除 Spring Boot 开发工具。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeDockerCompose
从重新打包的归档文件中排除 Spring Boot 开发服务。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeGroupIds
要排除的 groupId 名称的逗号分隔列表(精确匹配)。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludes
要排除的 artifact 定义集合。Exclude 元素定义了强制的 groupId 和 artifactId 组件以及可选的 classifier 组件。当配置为属性时,值应以逗号分隔,组件以冒号分隔:groupId:artifactId,groupId:artifactId:classifier
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
includes
要包含的 artifact 定义集合。Include 元素定义了强制的 groupId 和 artifactId 组件以及可选的 classifier 组件。当配置为属性时,值应以逗号分隔,组件以冒号分隔:groupId:artifactId,groupId:artifactId:classifier
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
layout
归档文件的类型(对应于其内部依赖项的布局方式)。可能的值为 JAR、WAR、ZIP、DIR、NONE。默认为根据归档类型推断的值。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
outputDirectory
包含生成的归档文件的目录。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
outputTimestamp
可重现输出归档条目的时间戳,格式可以是 ISO 8601 (yyyy-MM-dd’T’HH:mm:ssXXX) 或表示自纪元以来的秒数的 int。
名称 |
|
|---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
示例
自定义分类器
默认情况下,repackage 目标将原始工件替换为重新打包的工件。对于表示应用程序的模块来说,这是一个合理的行为,但如果您的模块用作另一个模块的依赖项,您需要为重新打包的工件提供一个分类器。原因是应用程序类被打包在 BOOT-INF/classes 中,因此依赖模块无法加载重新打包的 jar 的类。
如果出现这种情况,或者如果您希望保留原始工件并使用不同的分类器附加重新打包的工件,请按以下示例配置插件:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
如果您正在使用 spring-boot-starter-parent,则 repackage 目标将自动以 ID 为 repackage 的执行方式运行。在这种设置下,只需指定配置即可,如以下示例所示:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
此配置将生成两个工件:原始工件和由 repackage 目标生成的重新打包工件。两者都将透明地安装/部署。
您也可以使用相同的配置,如果您想以替换主工件的方式重新打包辅助工件。以下配置将安装/部署一个带有重新打包应用程序的单个 task 分类工件:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>task</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>task</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
由于 maven-jar-plugin 和 spring-boot-maven-plugin 在同一阶段运行,因此 jar 插件必须首先定义(以便在 repackage 目标之前运行)。同样,如果您使用 spring-boot-starter-parent,这可以简化如下:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<configuration>
<classifier>task</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>task</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
自定义名称
如果您需要重新打包的 jar 具有与项目 artifactId 属性定义的名称不同的本地名称,请使用标准的 finalName,如以下示例所示:
<project>
<build>
<finalName>my-app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
此配置将在 target/my-app.jar 中生成重新打包的工件。
本地重新打包工件
默认情况下,repackage 目标会将原始工件替换为可执行工件。如果您只需要部署原始 jar,但又希望能够使用常规文件名运行您的应用程序,请按如下方式配置插件:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
此配置生成两个工件:原始工件和由 repackage 目标生成的可执行工件。只有原始工件会被安装/部署。
自定义布局
Spring Boot 使用在附加 jar 文件中定义的自定义布局工厂重新打包此项目的 jar 文件,该文件作为构建插件的依赖项提供:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<layoutFactory implementation="com.example.CustomLayoutFactory">
<customProperty>value</customProperty>
</layoutFactory>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-layout</artifactId>
<version>0.0.1.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
布局工厂作为 LayoutFactory(来自 spring-boot-loader-tools)的实现提供,并在 pom 中明确指定。如果插件类路径上只有一个自定义 LayoutFactory 并且它列在 META-INF/spring.factories 中,则无需在插件配置中显式设置它。
如果设置了显式 layout,则始终忽略布局工厂。
依赖项排除
默认情况下,repackage 和 run 目标都将包含项目中定义的任何 provided 依赖项。Spring Boot 项目应将 provided 依赖项视为运行应用程序所需的“容器”依赖项。通常来说,Spring Boot 项目不被用作依赖项,因此不太可能拥有任何 optional 依赖项。当项目确实有可选依赖项时,它们也将被 repackage 和 run 目标包含。
其中一些依赖项可能根本不需要,并且应从可执行 jar 中排除。为保持一致性,在运行应用程序时也不应包含它们。
有两种方法可以从打包/运行时排除依赖项:
-
排除由
groupId和artifactId标识的特定工件,如果需要,可选地带有classifier。 -
排除属于给定
groupId的任何工件。
以下示例排除 com.example:module1,且仅排除该工件:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>com.example</groupId>
<artifactId>module1</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
此示例排除了属于 com.example 组的任何工件:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeGroupIds>com.example</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</build>
</project>
JAR 工具
当创建分层 jar 或 war 时,spring-boot-jarmode-tools jar 将作为依赖项添加到您的归档文件中。通过将此 jar 放在类路径上,您可以在特殊模式下启动您的应用程序,该模式允许引导代码运行与您的应用程序完全不同的东西,例如,提取层的代码。如果您希望排除此依赖项,可以按以下方式操作:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeTools>false</includeTools>
</configuration>
</plugin>
</plugins>
</build>
</project>
自定义层配置
默认设置将依赖项分为快照和非快照,但是,您可能有更复杂的规则。例如,您可能希望将项目中的公司特定依赖项隔离到专用层中。以下 layers.xml 配置显示了这样一种设置:
<layers xmlns="http://www.springframework.org/schema/boot/layers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
https://www.springframework.org/schema/boot/layers/layers-4.0.xsd">
<application>
<into layer="spring-boot-loader">
<include>org/springframework/boot/loader/**</include>
</into>
<into layer="application" />
</application>
<dependencies>
<into layer="snapshot-dependencies">
<include>*:*:*SNAPSHOT</include>
</into>
<into layer="company-dependencies">
<include>com.acme:*</include>
</into>
<into layer="dependencies"/>
</dependencies>
<layerOrder>
<layer>dependencies</layer>
<layer>spring-boot-loader</layer>
<layer>snapshot-dependencies</layer>
<layer>company-dependencies</layer>
<layer>application</layer>
</layerOrder>
</layers>
上述配置创建了一个额外的 company-dependencies 层,其中包含所有 com.acme groupId 的库。