打包可执行文件

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

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

注意:maven-war-pluginoutputFileNameMapping 功能当前不受支持。

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

该插件会重写您的清单,特别是它管理 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 的别名):使用 PropertiesLauncher 的类似于 JAR 的布局。

  • 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
	                      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> 将声明剩下的任何内容(在本例中,任何不是 SNAPSHOT 的依赖项)为 dependencies 层。

<application> 块有类似的规则。 首先为 spring-boot-loader 层声明 org/springframework/boot/loader/** 内容。 然后为 application 层声明任何剩余的类和资源。

注意:<into> 块定义的顺序通常与层的书写顺序不同。 因此,必须始终包含 <layerOrder> 元素,并且必须涵盖 <into> 块引用的所有层。

spring-boot:repackage

org.springframework.boot:spring-boot-maven-plugin:3.4.6

Repackage existing JAR and WAR archives so that they can be executed from the command line using java -jar. With layout=NONE can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).

Required parameters

Name Type Default

outputDirectory

File

${project.build.directory}

Optional parameters

Name Type Default

attach

boolean

true

classifier

String

embeddedLaunchScript

File

embeddedLaunchScriptProperties

Properties

excludeDevtools

boolean

true

excludeDockerCompose

boolean

true

excludeGroupIds

String

excludes

List

executable

boolean

false

includeSystemScope

boolean

false

includeTools

boolean

true

includes

List

layers

Layers

layout

LayoutType

layoutFactory

LayoutFactory

loaderImplementation

LoaderImplementation

mainClass

String

outputTimestamp

String

${project.build.outputTimestamp}

requiresUnpack

List

skip

boolean

false

Parameter details

attach

Attach the repackaged archive to be installed into your local Maven repository or deployed to a remote repository. If no classifier has been configured, it will replace the normal jar. If a classifier has been configured such that the normal jar and the repackaged jar are different, it will be attached alongside the normal jar. When the property is set to false, the repackaged archive will not be installed or deployed.

Name

attach

Type

boolean

Default value

true

User property

Since

1.4.0

classifier

Classifier to add to the repackaged archive. If not given, the main artifact will be replaced by the repackaged archive. If given, the classifier will also be used to determine the source archive to repackage: if an artifact with that classifier already exists, it will be used as source and replaced. If no such artifact exists, the main artifact will be used as source and the repackaged archive will be attached as a supplemental artifact with that classifier. Attaching the artifact allows to deploy it alongside to the original one, see the Maven documentation for more details.

Name

classifier

Type

java.lang.String

Default value

User property

Since

1.0.0

embeddedLaunchScript

The embedded launch script to prepend to the front of the jar if it is fully executable. If not specified the 'Spring Boot' default script will be used.

Name

embeddedLaunchScript

Type

java.io.File

Default value

User property

Since

1.3.0

embeddedLaunchScriptProperties

Properties that should be expanded in the embedded launch script.

Name

embeddedLaunchScriptProperties

Type

java.util.Properties

Default value

User property

Since

1.3.0

excludeDevtools

Exclude Spring Boot devtools from the repackaged archive.

Name

excludeDevtools

Type

boolean

Default value

true

User property

spring-boot.repackage.excludeDevtools

Since

1.3.0

excludeDockerCompose

Exclude Spring Boot dev services from the repackaged archive.

Name

excludeDockerCompose

Type

boolean

Default value

true

User property

spring-boot.repackage.excludeDockerCompose

Since

3.1.0

excludeGroupIds

Comma separated list of groupId names to exclude (exact match).

Name

excludeGroupIds

Type

java.lang.String

Default value

User property

spring-boot.excludeGroupIds

Since

1.1.0

excludes

Collection of artifact definitions to exclude. The Exclude element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

excludes

Type

java.util.List

Default value

User property

spring-boot.excludes

Since

1.1.0

executable

Make a fully executable jar for *nix machines by prepending a launch script to the jar. Currently, some tools do not accept this format so you may not always be able to use this technique. For example, jar -xf may silently fail to extract a jar or war that has been made fully-executable. It is recommended that you only enable this option if you intend to execute it directly, rather than running it with java -jar or deploying it to a servlet container.

Name

executable

Type

boolean

Default value

false

User property

Since

1.3.0

includeSystemScope

Include system scoped dependencies.

Name

includeSystemScope

Type

boolean

Default value

false

User property

Since

1.4.0

includeTools

Include JAR tools.

Name

includeTools

Type

boolean

Default value

true

User property

Since

3.3.0

includes

Collection of artifact definitions to include. The Include element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

includes

Type

java.util.List

Default value

User property

spring-boot.includes

Since

1.2.0

layers

Layer configuration with options to disable layer creation, exclude layer tools jar, and provide a custom layers configuration file.

Name

layers

Type

org.springframework.boot.maven.Layers

Default value

User property

Since

2.3.0

layout

The type of archive (which corresponds to how the dependencies are laid out inside it). Possible values are JAR, WAR, ZIP, DIR, NONE. Defaults to a guess based on the archive type.

Name

layout

Type

org.springframework.boot.maven.AbstractPackagerMojo$LayoutType

Default value

User property

spring-boot.repackage.layout

Since

1.0.0

layoutFactory

The layout factory that will be used to create the executable archive if no explicit layout is set. Alternative layouts implementations can be provided by 3rd parties.

Name

layoutFactory

Type

org.springframework.boot.loader.tools.LayoutFactory

Default value

User property

Since

1.5.0

loaderImplementation

The loader implementation that should be used.

Name

loaderImplementation

Type

org.springframework.boot.loader.tools.LoaderImplementation

Default value

User property

Since

3.2.0

mainClass

The name of the main class. If not specified the first compiled class found that contains a main method will be used.

Name

mainClass

Type

java.lang.String

Default value

User property

Since

1.0.0

outputDirectory

Directory containing the generated archive.

Name

outputDirectory

Type

java.io.File

Default value

${project.build.directory}

User property

Since

1.0.0

outputTimestamp

Timestamp for reproducible output archive entries, either formatted as ISO 8601 (yyyy-MM-dd’T’HH:mm:ssXXX) or an int representing seconds since the epoch.

Name

outputTimestamp

Type

java.lang.String

Default value

${project.build.outputTimestamp}

User property

Since

2.3.0

requiresUnpack

A list of the libraries that must be unpacked from uber jars in order to run. Specify each library as a <dependency> with a <groupId> and a <artifactId> and they will be unpacked at runtime.

Name

requiresUnpack

Type

java.util.List

Default value

User property

Since

1.1.0

skip

Skip the execution.

Name

skip

Type

boolean

Default value

false

User property

spring-boot.repackage.skip

Since

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
						  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 层,其中包含所有 com.acme groupId 的库。