打包可执行档案
该插件可以创建包含应用程序所有依赖项的可执行档案(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 生命周期 package
阶段构建的 jar
或 war
档案,包括项目中定义的任何 provided
依赖。如果需要排除某些依赖项,可以使用 exclude
选项之一;更多详情请参阅依赖排除。
默认情况下,原始(即不可执行的)artifact 会被重命名为 .original
,但也可以使用自定义分类器保留原始 artifact。
目前不支持 maven-war-plugin 的 outputFileNameMapping 特性。 |
spring-boot-devtools
和 spring-boot-docker-compose
模块默认会自动排除(您可以使用 excludeDevtools
和 excludeDockerCompose
属性控制)。为了使其在 war
打包中生效,必须将 spring-boot-devtools
和 spring-boot-docker-compose
依赖项设置为 optional
或使用 provided
范围。
该插件会重写您的 manifest 文件,特别是管理 Main-Class
和 Start-Class
条目。如果默认值不适用,您必须在 Spring Boot 插件中配置这些值,而不是在 jar 插件中。manifest 文件中的 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-3.4.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:3.4.5
重新打包现有的 JAR 和 WAR 档案,以便可以使用 java -jar
从命令行执行它们。使用 layout=NONE
也可以简单地用于打包带有嵌套依赖项的 JAR(且没有主类,因此不可执行)。
可选参数
名称 | 类型 | 默认值 |
---|---|---|
|
|
|
|
||
|
||
|
||
|
|
|
|
|
|
|
||
|
||
|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
|
|
||
|
|
参数详情
attach
将重新打包的档案附加到要安装到本地 Maven 仓库或部署到远程仓库的 artifact。如果未配置分类器,它将替换正常的 jar 文件。如果配置了 classifier
,使得正常 jar 和重新打包的 jar 不同,它将作为附加 artifact 与正常 jar 一同安装/部署。当该属性设置为 false
时,重新打包的档案将不会被安装或部署。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
classifier
要添加到重新打包档案的分类器。如果未指定,主 artifact 将被重新打包档案替换。如果指定,该分类器也将用于确定要重新打包的源档案:如果已存在具有该分类器的 artifact,则将其用作源并被替换。如果不存在此类 artifact,则将使用主 artifact 作为源,并将重新打包的档案作为带有该分类器的附加 artifact 附加。附加 artifact 允许将其与原始 artifact 一同部署,更多详细信息请参阅Maven 文档。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
embeddedLaunchScript
如果 jar 是完全可执行的,要添加到 jar 前面的嵌入式启动脚本。如果未指定,将使用 Spring Boot 的默认脚本。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
embeddedLaunchScriptProperties
应该在嵌入式启动脚本中展开的属性。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeDevtools
从重新打包的档案中排除 Spring Boot devtools。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeDockerCompose
从重新打包的档案中排除 Spring Boot dev services。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludeGroupIds
要排除的 groupId 名称的逗号分隔列表(精确匹配)。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
excludes
要排除的 artifact 定义集合。Exclude
元素定义了必需的 groupId
和 artifactId
组件以及可选的 classifier
组件。当配置为属性时,值应该是逗号分隔的,组件之间用冒号分隔:groupId:artifactId,groupId:artifactId:classifier
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
executable
通过在 jar 文件前添加启动脚本,为 *nix 系统创建完全可执行的 jar。目前,某些工具不接受此格式,因此您可能并非总是能够使用此技术。例如,jar -xf
可能会静默地无法解压已设置为完全可执行的 jar 或 war。建议您仅在打算直接执行它时才启用此选项,而不是通过 java -jar
运行或部署到 servlet 容器。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
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
) 或表示自 epoch 以来的秒数的 int
值。
名称 |
|
---|---|
类型 |
|
默认值 |
|
用户属性 |
|
自 |
|
示例
自定义分类器
默认情况下,repackage
目标将原始 artifact 替换为重新打包的 artifact。对于代表应用程序的模块来说,这是合理的行为,但如果您的模块被用作另一个模块的依赖项,您需要为重新打包的 artifact 提供一个分类器。这是因为应用程序类被打包在 BOOT-INF/classes
中,以便依赖模块无法加载重新打包 jar 中的类。
如果是这种情况,或者您希望保留原始 artifact 并使用不同的分类器附加重新打包的 artifact,请按以下示例配置插件
<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>
此配置将生成两个 artifact:原始 artifact 和由 repackage 目标生成的重新打包 artifact。两者都将透明地安装/部署。
如果您想以与替换主 artifact 相同的方式重新打包次要 artifact,也可以使用相同的配置。以下配置会安装/部署一个带有重新打包应用程序的、被分类为 task
的单个 artifact
<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
中生成重新打包的 artifact。
本地重新打包 artifact
默认情况下,repackage
目标将原始 artifact 替换为可执行 artifact。如果您只需要部署原始 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>
此配置生成两个 artifact:原始 artifact 和由 repackage
目标生成的可执行 artifact。只有原始 artifact 会被安装/部署。
自定义布局
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 中明确指定。如果在插件 classpath 上只有一个自定义 LayoutFactory
,并且它列在 META-INF/spring.factories
中,则无需在插件配置中显式设置它。
如果设置了显式布局,则始终忽略布局工厂。
依赖排除
默认情况下,repackage
和 run
目标都会包含项目中定义的任何 provided
依赖项。Spring Boot 项目应将 provided
依赖项视为运行应用程序所需的“容器”依赖项。一般来说,Spring Boot 项目不被用作依赖项,因此不太可能具有任何 optional
依赖项。当项目确实有 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>
自定义分层配置
默认设置将依赖项分为 snapshot 和非 snapshot,但是,您可能有更复杂的规则。例如,您可能希望在专用分层中隔离项目的公司特定依赖项。以下 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-3.4.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
分层,其中包含所有 groupId 为 com.acme
的库。