嵌套 JAR 文件
Java 并未提供任何标准的方式来加载嵌套的 JAR 文件(即本身包含在 JAR 文件中的 JAR 文件)。如果你需要分发一个自包含的应用程序,并且希望无需解压即可从命令行运行它,这可能会带来问题。
为了解决这个问题,许多开发者使用“shaded” jar。一个 shaded jar 会将所有 jar 中的所有类打包到一个单一的“uber jar”中。shaded jar 的问题在于,很难看出应用程序中实际包含了哪些库。如果在多个 jar 中使用了相同的文件名(但内容不同),这也可能会带来问题。Spring Boot 采取了不同的方法,允许你直接将 jar 嵌套在一起。
可执行 Jar 文件结构
Spring Boot Loader 兼容的 jar 文件应按以下方式组织:
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
应用程序类应放置在嵌套的 BOOT-INF/classes
目录中。依赖项应放置在嵌套的 BOOT-INF/lib
目录中。
可执行的 WAR 文件结构
Spring Boot Loader 兼容的 war 文件应按照以下方式构建:
example.war
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-WEB-INF
+-classes
| +-com
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
| +-dependency1.jar
| +-dependency2.jar
+-lib-provided
+-servlet-api.jar
+-dependency3.jar
依赖项应放置在嵌套的 WEB-INF/lib
目录中。在嵌入式环境下运行所需但在部署到传统 web 容器时不需要的任何依赖项应放置在 WEB-INF/lib-provided
中。
索引文件
Spring Boot Loader 兼容的 jar 和 war 归档文件可以在 BOOT-INF/
目录下包含额外的索引文件。classpath.idx
文件可以同时用于 jar 和 war,它提供了将 jar 添加到类路径的顺序。layers.idx
文件仅适用于 jar,它允许将 jar 拆分为逻辑层,以便用于 Docker/OCI 镜像的创建。
索引文件遵循 YAML 兼容的语法,以便第三方工具能够轻松解析。然而,这些文件并不在内部作为 YAML 解析,它们必须严格按照以下描述的格式编写才能被使用。
类路径索引
类路径索引文件可以放置在 BOOT-INF/classpath.idx
中。通常情况下,它是由 Spring Boot 的 Maven 和 Gradle 构建插件自动生成的。它按顺序提供了一个 jar 文件名称列表(包括目录),这些文件应该被添加到类路径中。当由构建插件生成时,这种类路径顺序与构建系统用于运行和测试应用程序的顺序相匹配。每一行必须以短横线和空格("-·"
)开头,并且名称必须用双引号括起来。
例如,给定以下 jar 文件:
example.jar
|
+-META-INF
| +-...
+-BOOT-INF
+-classes
| +...
+-lib
+-dependency1.jar
+-dependency2.jar
索引文件将如下所示:
- "BOOT-INF/lib/dependency2.jar"
- "BOOT-INF/lib/dependency1.jar"
Spring Boot 仅在通过 java -jar
执行 jar 或 war 文件时使用类路径索引文件。在从 IDE 运行应用程序或使用 Maven 的 spring-boot:run
或 Gradle 的 bootRun
时,不会使用该文件。
启用可重现构建时,classpath 索引文件中的条目会按字母顺序排序。
层索引
层索引文件可以存放在 BOOT-INF/layers.idx
中。它提供了层的列表以及应该包含在这些层中的 jar 部分。层的书写顺序应与它们添加到 Docker/OCI 镜像中的顺序一致。层名称以带引号的字符串形式书写,前缀为短横线加空格 ("-·"
),并以冒号 (":"
) 结尾。层内容可以是文件或目录名称,以带引号的字符串形式书写,前缀为两个空格加短横线加空格 ("··-·"
)。目录名称以 /
结尾,而文件名称则没有。当使用目录名称时,表示该目录中的所有文件都位于同一层。
一个典型的图层索引示例如下:
- "dependencies":
- "BOOT-INF/lib/dependency1.jar"
- "BOOT-INF/lib/dependency2.jar"
- "application":
- "BOOT-INF/classes/"
- "META-INF/"