可执行归档包的打包
该插件可以创建包含应用所有依赖项的可执行归档(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
选项之一,详见 依赖排除。
原始(即不可执行的)构件默认会被重命名为 .original
,也可以通过自定义classifier保留原始构件。
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
,以避免在servlet容器部署war时发生冲突。 -
ZIP
(DIR
的别名):类似于JAR
布局,使用PropertiesLauncher
。 -
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
: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.5.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>
块定义各层写入顺序。
在 <application>
和 <dependencies>
部分可嵌套 <into>
块以声明某层内容。
这些块按定义顺序自上而下依次评估。
未被前面块声明的内容会留给后续块处理。
<into>
块通过嵌套 <include>
和 <exclude>
元素声明内容。
<application>
部分使用Ant风格路径匹配进行包含/排除。
<dependencies>
部分使用 group:artifact[:version]
模式。
还可通过 <includeModuleDependencies />
和 <excludeModuleDependencies />
包含或排除本地模块依赖。
如未定义 <include>
,则所有(未被前面块声明的)内容都将被包含。
如未定义 <exclude>
,则不做任何排除。
从上面的 <dependencies>
示例可见,第一个 <into>
会将所有模块依赖声明到 application.layer
。
下一个 <into>
会将所有SNAPSHOT依赖声明到 snapshot-dependencies
层。
最后一个 <into>
会将剩余内容(即非SNAPSHOT依赖)声明到 dependencies
层。
<application>
块规则类似。
首先将 org/springframework/boot/loader/**
内容声明到 spring-boot-loader
层。
然后将剩余类和资源声明到 application
层。
<into> 块的定义顺序通常与层的写入顺序不同。
因此 <layerOrder> 元素必须始终包含,且 必须 覆盖所有 <into> 块引用的层。
|
spring-boot:repackage
org.springframework.boot:spring-boot-maven-plugin:3.5.0
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).
Optional parameters
Name | Type | Default |
---|---|---|
|
|
|
|
||
|
||
|
||
|
|
|
|
|
|
|
||
|
||
|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
|
|
||
|
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
embeddedLaunchScriptProperties
Properties that should be expanded in the embedded launch script.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
excludeDevtools
Exclude Spring Boot devtools from the repackaged archive.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
excludeDockerCompose
Exclude Spring Boot dev services from the repackaged archive.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
excludeGroupIds
Comma separated list of groupId names to exclude (exact match).
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
includeSystemScope
Include system scoped dependencies.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
includeTools
Include JAR tools.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
layers
Layer configuration with options to disable layer creation, exclude layer tools jar, and provide a custom layers configuration file.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
loaderImplementation
The loader implementation that should be used.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
mainClass
The name of the main class. If not specified the first compiled class found that contains a main
method will be used.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
outputDirectory
Directory containing the generated archive.
Name |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
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 |
|
---|---|
Type |
|
Default value |
|
User property |
|
Since |
|
示例
自定义Classifier
默认情况下,repackage
目标会用重打包后的构件替换原始构件。
这对于代表应用的模块来说是合理的,但如果你的模块作为其他模块的依赖使用,则需要为重打包构件提供一个classifier。
原因在于应用类被打包进 BOOT-INF/classes
,依赖模块无法加载重打包jar的类。
如遇此情况,或希望保留原始构件并以不同classifier附加重打包构件,可按如下方式配置插件:
<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
classifier 安装/部署为单独构件:
<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中显式指定。
若插件classpath上只有一个自定义 LayoutFactory
且已在 META-INF/spring.factories
中列出,则无需在插件配置中显式设置。
如显式设置了 layout,则总会忽略布局工厂。
依赖排除
默认情况下,repackage
和 run
目标会包含项目中定义的所有 provided
依赖。
Spring Boot项目应将 provided
依赖视为运行应用所需的“容器”依赖。
一般来说,Spring Boot项目不会作为依赖使用,因此通常不会有任何 optional
依赖。
如项目确有可选依赖,这些依赖也会被 repackage
和 run
目标包含。
部分依赖可能完全不需要,应从可执行jar中排除。 为保持一致性,运行应用时也不应包含这些依赖。
可通过两种方式排除运行时打包/使用的依赖:
-
排除由
groupId
和artifactId
唯一标识的特定artifact,必要时可加classifier
。 -
排除属于指定
groupId
的所有artifact。
以下示例排除了 com.example:module1
,且仅排除此artifact:
<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
组的artifact:
<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.5.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 的库。