打包可执行归档文件

该插件可以创建包含应用程序所有依赖项的可执行归档文件(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 生命周期打包阶段构建的 jarwar 归档文件,包括项目中定义的任何 provided 依赖项。如果需要排除其中一些依赖项,可以使用其中一个 exclude 选项;有关更多详细信息,请参阅 依赖项排除

默认情况下,原始(即不可执行的)工件重命名为 .original,但也可以使用自定义分类器保留原始工件。

目前不支持 maven-war-pluginoutputFileNameMapping 功能。

spring-boot-devtoolsspring-boot-docker-compose 模块默认情况下会自动排除(可以使用 excludeDevtoolsexcludeDockerCompose 属性控制此行为)。为了使这与 war 打包一起工作,spring-boot-devtoolsspring-boot-docker-compose 依赖项必须设置为 optional 或使用 provided 范围。

插件会重写您的清单,特别是它会管理 Main-ClassStart-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 属性默认为由归档类型(jarwar)确定的值。以下布局可用

  • JAR:常规可执行 JAR 布局。

  • WAR:可执行 WAR 布局。provided 依赖项放置在 WEB-INF/lib-provided 中,以避免在 war 部署到 servlet 容器时发生任何冲突。

  • ZIPDIR 的别名):类似于使用 PropertiesLauncherJAR 布局。

  • NONE:捆绑所有依赖项和项目资源。不捆绑引导加载程序。

分层 Jar 或 War

重新打包的 jar 分别在 BOOT-INF/classesBOOT-INF/lib 中包含应用程序的类和依赖项。类似地,可执行 war 在 WEB-INF/classes 中包含应用程序的类,在 WEB-INF/libWEB-INF/lib-provided 中包含依赖项。对于需要从 jar 或 war 的内容构建 docker 镜像的情况,能够进一步分离这些目录非常有用,以便可以将它们写入不同的层。

分层归档使用与常规重新打包的 jar 或 war 相同的布局,但包含一个描述每个层的附加元数据文件。

默认情况下,定义以下层

  • dependencies 用于任何版本不包含 SNAPSHOT 的依赖项。

  • spring-boot-loader 用于加载程序类。

  • snapshot-dependencies 用于任何版本包含 SNAPSHOT 的依赖项。

  • application 用于本地模块依赖项、应用程序类和资源。

模块依赖项是通过查看当前构建中包含的所有模块来识别的。如果模块依赖项只能因为已安装到 Maven 的本地缓存中且不是当前构建的一部分而得以解析,则它将被识别为常规依赖项。

层的顺序很重要,因为它决定了应用程序的一部分发生变化时之前层被缓存的可能性。默认顺序为 dependenciesspring-boot-loadersnapshot-dependenciesapplication。内容变化可能性最低的应该放在最前面,然后是变化可能性更高的层。

重新打包的归档文件默认包含 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
	                      layers-xsd: https://www.springframework.org/schema/boot/layers/layers-3.3.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 风格的路径匹配进行 include/exclude 表达式。<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.3.5

重新打包现有的 JAR 和 WAR 归档文件,以便可以使用 java -jar 从命令行执行它们。使用 layout=NONE 也可以简单地用于打包包含嵌套依赖项的 JAR(并且没有主类,因此不可执行)。

必需参数

名称 类型 默认值

outputDirectory

文件

${project.build.directory}

可选参数

名称 类型 默认值

attach

布尔值

true

classifier

字符串

embeddedLaunchScript

文件

embeddedLaunchScriptProperties

属性

excludeDevtools

布尔值

true

excludeDockerCompose

布尔值

true

excludeGroupIds

字符串

excludes

列表

executable

布尔值

false

includeSystemScope

布尔值

false

includeTools

布尔值

true

includes

列表

layers

layout

LayoutType

layoutFactory

LayoutFactory

loaderImplementation

LoaderImplementation

mainClass

字符串

outputTimestamp

字符串

${project.build.outputTimestamp}

requiresUnpack

列表

skip

布尔值

false

参数详细信息

attach

将重新打包的归档文件附加到您的本地 Maven 存储库中或部署到远程存储库中。如果没有配置分类器,它将替换正常的 jar。如果已配置 classifier 使得正常的 jar 和重新打包的 jar 不同,则它将与正常的 jar 一起附加。当属性设置为 false 时,重新打包的归档文件将不会安装或部署。

名称

attach

类型

布尔值

默认值

true

用户属性

1.4.0

classifier

要添加到重新打包的归档文件的分类器。如果未给出,则主工件将被重新打包的归档文件替换。如果给出,分类器也将用于确定要重新打包的源归档文件:如果已存在具有该分类器的工件,则它将用作源并被替换。如果没有这样的工件,则主工件将用作源,并且重新打包的归档文件将作为具有该分类器的补充工件附加。附加工件允许将其与原始工件一起部署,请参阅 Maven 文档以获取更多详细信息

名称

classifier

类型

java.lang.String

默认值

用户属性

1.0.0

embeddedLaunchScript

如果 jar 是完全可执行的,则要预先添加到 jar 前面的嵌入式启动脚本。如果未指定,则将使用“Spring Boot”默认脚本。

名称

embeddedLaunchScript

类型

java.io.File

默认值

用户属性

1.3.0

embeddedLaunchScriptProperties

应在嵌入式启动脚本中扩展的属性。

名称

embeddedLaunchScriptProperties

类型

java.util.Properties

默认值

用户属性

1.3.0

excludeDevtools

从重新打包的归档文件中排除 Spring Boot 开发工具。

名称

excludeDevtools

类型

布尔值

默认值

true

用户属性

spring-boot.repackage.excludeDevtools

1.3.0

excludeDockerCompose

从重新打包的归档文件中排除 Spring Boot 开发服务。

名称

excludeDockerCompose

类型

布尔值

默认值

true

用户属性

spring-boot.repackage.excludeDockerCompose

3.1.0

excludeGroupIds

要排除的 groupId 名称的逗号分隔列表(完全匹配)。

名称

excludeGroupIds

类型

java.lang.String

默认值

用户属性

spring-boot.excludeGroupIds

1.1.0

excludes

要排除的工件定义的集合。Exclude 元素定义了必需的 groupIdartifactId 组件以及可选的 classifier 组件。当配置为属性时,值应以逗号分隔,组件以冒号分隔:groupId:artifactId,groupId:artifactId:classifier

名称

excludes

类型

java.util.List

默认值

用户属性

spring-boot.excludes

1.1.0

executable

通过在 jar 文件前面添加启动脚本,为 *nix 系统创建可执行的 jar 文件。<p> 目前,某些工具不接受此格式,因此您可能无法始终使用此技术。例如,jar -xf 可能会静默地失败,无法提取已设为可执行文件的 jar 或 war 文件。建议您仅在打算直接执行它时启用此选项,而不是使用 java -jar 执行它或将其部署到 servlet 容器中。

名称

executable

类型

布尔值

默认值

false

用户属性

1.3.0

includeSystemScope

包含系统范围的依赖项。

名称

includeSystemScope

类型

布尔值

默认值

false

用户属性

1.4.0

includeTools

包含 JAR 工具。

名称

includeTools

类型

布尔值

默认值

true

用户属性

3.3.0

includes

要包含的构件定义集合。Include 元素定义必需的 groupIdartifactId 组件以及可选的 classifier 组件。当配置为属性时,值应以逗号分隔,组件以冒号分隔:groupId:artifactId,groupId:artifactId:classifier

名称

includes

类型

java.util.List

默认值

用户属性

spring-boot.includes

1.2.0

layers

层配置,包括禁用层创建、排除层工具 jar 以及提供自定义层配置文件的选项。

名称

layers

类型

org.springframework.boot.maven.Layers

默认值

用户属性

2.3.0

layout

归档文件的类型(对应于依赖项在其中如何布局)。可能的值为 JARWARZIPDIRNONE。默认为基于归档文件类型进行猜测。

名称

layout

类型

org.springframework.boot.maven.AbstractPackagerMojo$LayoutType

默认值

用户属性

spring-boot.repackage.layout

1.0.0

layoutFactory

如果未设置显式布局,则用于创建可执行归档文件的布局工厂。第三方可以提供替代的布局实现。

名称

layoutFactory

类型

org.springframework.boot.loader.tools.LayoutFactory

默认值

用户属性

1.5.0

loaderImplementation

应该使用的加载器实现。

名称

loaderImplementation

类型

org.springframework.boot.loader.tools.LoaderImplementation

默认值

用户属性

3.2.0

mainClass

主类的名称。如果未指定,则将使用找到的第一个包含 main 方法的编译类。

名称

mainClass

类型

java.lang.String

默认值

用户属性

1.0.0

outputDirectory

包含生成的归档文件的目录。

名称

outputDirectory

类型

java.io.File

默认值

${project.build.directory}

用户属性

1.0.0

outputTimestamp

用于可重复生成输出归档文件条目的时间戳,格式为 ISO 8601(yyyy-MM-dd’T’HH:mm:ssXXX)或表示自纪元以来的秒数的 int

名称

outputTimestamp

类型

java.lang.String

默认值

${project.build.outputTimestamp}

用户属性

2.3.0

requiresUnpack

必须从 uber jar 文件中解压才能运行的库列表。将每个库指定为具有 <groupId><artifactId><dependency>,并在运行时将其解压。

名称

requiresUnpack

类型

java.util.List

默认值

用户属性

1.1.0

skip

跳过执行。

名称

skip

类型

布尔值

默认值

false

用户属性

spring-boot.repackage.skip

1.2.0

示例

自定义分类器

默认情况下,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-pluginspring-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,则始终会忽略布局工厂。

依赖项排除

默认情况下,repackagerun 目标都将包含项目中定义的任何 provided 依赖项。Spring Boot 项目应将 provided 依赖项视为运行应用程序所需的“容器”依赖项。一般来说,Spring Boot 项目不用作依赖项,因此不太可能有任何 optional 依赖项。当项目确实具有可选依赖项时,repackagerun 目标也将包含它们。

其中一些依赖项可能根本不需要,应从可执行 jar 文件中排除。为了保持一致性,在运行应用程序时也不应存在这些依赖项。

可以通过两种方法将依赖项从打包/运行时使用中排除。

  • 排除由 groupIdartifactId 标识的特定构件,如果需要,还可以使用 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
						  layers-xsd: https://www.springframework.org/schema/boot/layers/layers-3.3.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 的库。