跳到主要内容

打包可执行档案

DeepSeek V3 中英对照 Packaging Executable Archives

该插件可以创建可执行的存档文件(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>
xml
注意

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 依赖必须设置为 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>
xml

layout 属性默认值取决于归档类型(jarwar)。以下是可用的布局:

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

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

  • ZIP(别名 DIR):类似于使用 PropertiesLauncherJAR 布局。

  • NONE: 打包所有依赖项和项目资源。不打包引导加载器。

分层 Jar 或 War

重新打包的 jar 文件将应用程序的类放置在 BOOT-INF/classes 中,而依赖项则放置在 BOOT-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>
xml

自定义层配置

根据您的应用程序需求,您可能希望调整图层的创建方式并添加新的图层。这可以通过使用一个单独的配置文件来实现,该文件应按如下所示进行注册:

<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>
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="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>
xml

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> 块有类似的规则。首先将 org/springframework/boot/loader/** 内容分配给 spring-boot-loader 层,然后将剩余的类和资源分配给 application 层。

备注

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

spring-boot:repackage

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

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

必填参数

名称类型默认值
outputDirectoryFile${project.build.directory}

可选参数

名称类型默认值
attachbooleantrue
classifierString
embeddedLaunchScriptFile
embeddedLaunchScriptPropertiesProperties
excludeDevtoolsbooleantrue
excludeDockerComposebooleantrue
excludeGroupIdsString
excludesList
executablebooleanfalse
includeSystemScopebooleanfalse
includeToolsbooleantrue
includesList
layers[Layers](https://docs.spring.io/spring-boot/maven-plugin/api/java/org/springframework/boot/maven/Layers.html)
layout[LayoutType](https://docs.spring.io/spring-boot/maven-plugin/api/java/org/springframework/boot/maven/AbstractPackagerMojo.LayoutType.html)
layoutFactory[LayoutFactory](https://docs.spring.io/spring-boot/api/java/org/springframework/boot/loader/tools/LayoutFactory.html)
loaderImplementation[LoaderImplementation](https://docs.spring.io/spring-boot/api/java/org/springframework/boot/loader/tools/LoaderImplementation.html)
mainClassString
outputTimestampString${project.build.outputTimestamp}
requiresUnpackList
skipbooleanfalse

参数详细信息

attach

将重新打包的归档文件附加到本地 Maven 仓库中安装或部署到远程仓库。如果未配置 classifier,它将替换普通的 jar 文件。如果配置了 classifier,使得普通 jar 和重新打包的 jar 不同,它将与普通 jar 一起附加。当该属性设置为 false 时,重新打包的归档文件将不会被安装或部署。

名称attach
类型boolean
默认值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 devtools。

名称excludeDevtools
类型boolean
默认值true
用户属性spring-boot.repackage.excludeDevtools
自版本1.3.0

excludeDockerCompose

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

名称excludeDockerCompose
类型boolean
默认值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。目前,某些工具不接受这种格式,因此你可能无法总是使用此技术。例如,jar -xf 可能会在提取已完全可执行的 jar 或 war 文件时静默失败。建议仅在打算直接执行它时启用此选项,而不是使用 java -jar 运行或将其部署到 servlet 容器中。

名称executable
类型boolean
默认值false
用户属性
自版本1.3.0

includeSystemScope

包含系统范围内的依赖项。

名称includeSystemScope
类型boolean
默认值false
用户属性
自版本1.4.0

includeTools

包含 JAR 工具。

名称includeTools
类型boolean
默认值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](https://docs.spring.io/spring-boot/maven-plugin/api/java/org/springframework/boot/maven/Layers.html)
默认值
用户属性
自版本2.3.0

layout

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

名称layout
类型[org.springframework.boot.maven.AbstractPackagerMojo$LayoutType](https://docs.spring.io/spring-boot/maven-plugin/api/java/org/springframework/boot/maven/AbstractPackagerMojo.LayoutType.html)
默认值
用户属性spring-boot.repackage.layout
自版本1.0.0

layoutFactory

如果未设置明确的布局,将使用此布局工厂来创建可执行归档文件。第三方可以提供替代布局实现。

名称layoutFactory
类型[org.springframework.boot.loader.tools.LayoutFactory](https://docs.spring.io/spring-boot/api/java/org/springframework/boot/loader/tools/LayoutFactory.html)
默认值
用户属性
自版本1.5.0

loaderImplementation

应使用的加载器实现。

名称loaderImplementation
类型[org.springframework.boot.loader.tools.LoaderImplementation](https://docs.spring.io/spring-boot/api/java/org/springframework/boot/loader/tools/LoaderImplementation.html)
默认值
用户属性
自版本3.2.0

mainClass

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

NamemainClass
Typejava.lang.String
Default value
User property
Since1.0.0

outputDirectory

包含生成的存档的目录。

NameoutputDirectory
Typejava.io.File
Default value${project.build.directory}
User property
Since1.0.0

outputTimestamp

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

NameoutputTimestamp
Typejava.lang.String
Default value${project.build.outputTimestamp}
User property
Since2.3.0

requiresUnpack

必须从 uber jars 中解压的库列表,以便运行。将每个库指定为带有 <groupId><artifactId><dependency>,它们将在运行时解压。

NamerequiresUnpack
Typejava.util.List
Default value
User property
Since1.1.0

skip

跳过执行。

Nameskip
Typeboolean
Default valuefalse
User propertyspring-boot.repackage.skip
Since1.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>
xml

如果你使用的是 spring-boot-starter-parentrepackage 目标会在一个 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>
xml

此配置将生成两个构件:原始构件和由 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>
xml

由于 maven-jar-pluginspring-boot-maven-plugin 在同一个阶段运行,因此首先定义 jar 插件非常重要(以便它在重新打包目标之前运行)。同样,如果你使用 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>
xml

自定义名称

如果你需要重新打包的 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>
xml

此配置将会在 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>
xml

此配置会生成两个构件:原始构件和由 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>
xml

布局工厂作为 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>
xml

此示例排除了属于 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>
xml

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>
xml

自定义层配置

默认设置将依赖项分为快照和非快照,但您可能有更复杂的规则。例如,您可能希望将项目中特定于公司的依赖项隔离到一个专用层中。以下 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>
xml

上述配置会创建一个额外的 company-dependencies 层,其中包含所有 groupIdcom.acme 的库。