嵌套 JAR
Java 不提供任何标准方式来加载嵌套的 jar 文件(即,本身包含在 jar 中的 jar 文件)。如果你需要分发一个可以从命令行运行而无需解压的自包含应用程序,这可能会带来问题。
为了解决这个问题,许多开发者使用“着色(shaded)”jar。着色 jar 将所有 jar 中的所有类打包成一个单独的“uber jar”。着色 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/ 目录下包含额外的索引文件。jar 和 war 文件都可以提供 classpath.idx 文件,它提供了 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 仅在 jar 或 war 文件使用 java -jar 执行时使用类路径索引文件。在 IDE 中运行应用程序或使用 Maven 的 spring-boot:run 或 Gradle 的 bootRun 时不使用它。 |
| 启用可重现构建时,类路径索引文件中的条目按字母顺序排序。 |
层索引
层索引文件可以放在 BOOT-INF/layers.idx 中。它提供了层列表以及每个层应包含的 jar 部分。层按照应添加到 Docker/OCI 镜像的顺序写入。层名称以带破折号空格 ("-·") 前缀和冒号 (":") 后缀的带引号字符串形式写入。层内容是文件或目录名,以空格空格破折号空格 ("··-·") 为前缀的带引号字符串形式写入。目录名以 / 结尾,文件名则不。当使用目录名时,意味着该目录中的所有文件都在同一层中。
层索引的典型示例如下:
- "dependencies":
- "BOOT-INF/lib/dependency1.jar"
- "BOOT-INF/lib/dependency2.jar"
- "application":
- "BOOT-INF/classes/"
- "META-INF/"