回答
Spring Boot 的 jar 之所以可以直接运行,主要是因为它是一个可执行的 Jar(Fat Jar),并且内部集成了一个嵌入式的 Servlet 容器(比如 Tomcat、Jetty 或 Undertow)。这种方式可以直接通过 java -jar
命令运行,而无需单独部署到外部应用服务器中。这种运行机制的核心在于 Spring Boot 使用了一个特殊的启动类 org.springframework.boot.loader.JarLauncher
,以及自定义的类加载机制。
简单点说就是:
- Spring Boot 将所有的依赖和资源打包到一个单独的 Jar 文件中。
- 使用
JarLauncher
类管理启动流程,内部就是通过反射机制执行我们的main()
。 - 提供嵌入式容器,让应用直接运行。
详解
可执行的 jar
Spring Boot 提供了一个名叫 spring-boot-maven-plugin
的 maven 项目打包插件,如下:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
通过这个插件,我们可以非常方便地将 Spring Boot 项目打包成一个可执行的 jar,我们先看看它的结构:
sk-website-2.3.6.4.jar
:是通过 Spring Boot 打包插件采用新的格式打成 Fat Jar,包含了所有的依赖和资源。sk-website-2.3.6.4.jar.original
:是通过 Java 原生的打包方式生成的,仅仅只包含了项目本身的内容。
我们将 sk-website-2.3.6.4.jar
打开,会看到如下结构:
BOOT-INF 文件夹
Spring Boot 定义的目录,用于存放应用程序的内容以及相关依赖。
BOOT-INF/classes/
存放编译后的应用程序内容,即对应项目里面的 src/main/java
文件夹内容和资源文件,即对应项目里面的 src/main/resources
。
- BOOT-INF/lib/
存放所有外部依赖的 jar 文件。
META-INF 文件夹
主要是包含了 jar 的元数据,文件中的 MANIFEST.MF
包含了启动类的定义和其他 jar 元信息,如下: