打包可执行归档文件
该插件可以创建可执行的归档文件(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 作用域。同时请注意,可选依赖默认不会被包含。如果你已将这些模块定义为可选依赖,则还需要将 includeOptional 属性设置为 true。
该插件会重写你的 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:打包所有依赖项和项目资源,但不包含引导加载器(bootstrap loader)。
分层 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-4.0.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> 部分在 include/exclude 表达式中使用 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:4.0.2
重新打包现有的 JAR 和 WAR 归档文件,使其可以通过命令行使用 java -jar 执行。当使用 layout=NONE 时,也可以仅用于打包一个包含嵌套依赖项的 JAR(不包含主类,因此不可执行)。
必需参数
| 名称 | 类型 | 默认值 |
|---|---|---|
| outputDirectory | File | ${project.build.directory} |
可选参数
| 名称 | 类型 | 默认值 |
|---|---|---|
| attach | boolean | true |
| classifier | String | |
| excludeDevtools | boolean | true |
| excludeDockerCompose | boolean | true |
| excludeGroupIds | String | |
| excludes | List | |
| includeOptional | boolean | false |
| includeSystemScope | boolean | false |
| includeTools | boolean | true |
| includes | List | |
| 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) | |
| mainClass | String | |
| outputTimestamp | String | ${project.build.outputTimestamp} |
| requiresUnpack | List | |
| skip | boolean | false |
参数详情
attach
将重新打包的归档文件附加到本地 Maven 仓库以进行安装,或部署到远程仓库。如果没有配置 classifier,它将替换正常的 jar 文件。如果配置了 classifier,使得正常的 jar 文件与重新打包的 jar 文件不同,则它将与正常的 jar 文件一同附加。当该属性设置为 false 时,重新打包的归档文件将不会被安装或部署。
attach | |
|---|---|
| 类型 | boolean |
| 默认值 | true |
| 用户属性 | |
| 自 | 1.4.0 |
classifier
要添加到重新打包的归档文件中的 classifier。如果未指定,则主构件(main artifact)将被重新打包的归档文件替换。如果指定了 classifier,该 classifier 还将用于确定要重新打包的源归档文件:如果已存在具有该 classifier 的构件,则将其用作源并进行替换;如果不存在这样的构件,则使用主构件作为源,而重新打包后的归档文件将作为带有该 classifier 的附加构件(supplemental artifact)进行附加。附加该构件可以使其与原始构件一同部署,更多详情请参见 Maven 官方文档。
classifier | |
|---|---|
| 类型 | java.lang.String |
| 默认值 | |
| 用户属性 | |
| 起始版本 | 1.0.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 元素定义了必需的 groupId 和 artifactId 组件,以及一个可选的 classifier 组件。当配置为属性时,值应以逗号分隔,各组件之间用冒号分隔:groupId:artifactId,groupId:artifactId:classifier
excludes | |
|---|---|
| 类型 | java.util.List |
| 默认值 | |
| 用户属性 | spring-boot.excludes |
| 起始版本 | 1.1.0 |
includeOptional
包含可选依赖项。
includeOptional | |
|---|---|
| 类型 | boolean |
| 默认值 | false |
| 用户属性 | |
| 起始版本 | 3.5.7 |
includeSystemScope
包含 system 范围的依赖项。
includeSystemScope | |
|---|---|
| 类型 | boolean |
| 默认值 | false |
| 用户属性 | |
| 起始版本 | 1.4.0 |
includeTools
包含 JAR 工具。
includeTools | |
|---|---|
| 类型 | boolean |
| 默认值 | true |
| 用户属性 | |
| 自 | 3.3.0 |
includes
要包含的构件定义集合。Include 元素定义了必需的 groupId 和 artifactId 组件,以及一个可选的 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
归档文件的类型(对应于其内部依赖项的布局方式)。可能的值有 JAR、WAR、ZIP、DIR、NONE。默认值根据归档文件类型进行猜测。
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 |
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,表示自 Unix 纪元以来的秒数。
outputTimestamp | |
|---|---|
| 类型 | java.lang.String |
| 默认值 | ${project.build.outputTimestamp} |
| 用户属性 | |
| 自 | 2.3.0 |
requiresUnpack
一个必须从 uber jar 中解压出来的库列表,以便运行。将每个库指定为一个 <dependency>,包含 <groupId> 和 <artifactId>,它们将在运行时被解压。
requiresUnpack | |
|---|---|
| 类型 | java.util.List |
| 默认值 | |
| 用户属性 | |
| 自 | 1.1.0 |
skip
跳过执行。
skip | |
|---|---|
| 类型 | boolean |
| 默认值 | false |
| 用户属性 | spring-boot.repackage.skip |
| 起始版本 | 1.2.0 |
示例
Custom 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 分类器的构件,其中包含重新打包后的应用程序:
<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 文件作为构建插件的依赖项提供)来重新打包该项目的 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,则布局工厂(layout factories)将始终被忽略。
依赖排除
默认情况下,repackage 和 run 目标都会包含项目中定义的任何 provided 依赖。Spring Boot 项目应将 provided 依赖视为运行应用程序所需的“容器”依赖。一般来说,Spring Boot 项目不会被用作依赖项,因此不太可能包含任何 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 位于 classpath 上时,你可以以一种特殊模式启动应用程序,该模式允许引导代码运行与你的应用程序完全不同的内容,例如用于提取分层内容的工具。如果你希望排除此依赖项,可以按以下方式操作:
<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-4.0.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 的库。