SpringBoot的 jar 可以直接运行
SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
打包完生成的executable-jar-1.0-SNAPSHOT.jar内部的结构如下
根目录
|-- BOOT-INF
|-- classes
|-- lib
|-- META-INF
|-- org
- BOOT-INF 目录
- classes 目录中存放
项目代码对应的 .class文件
- lib 目录中存放
项目相关的依赖包
,依赖包以 jar包 的方式存放(jar文件中存放jar文件,有个专门称呼叫 “FatJar”
- META-INF
- 存放清单文件,其内容描述当前可执行 jar 包的基本信息
- 其中,有两个主要的描述信息:
- Main-Class
- 描述 jar包 的入口文件(main 方法所在的类)
- Spring 框架固定是
org.springframework.boot.loader.JarLauncher
- 定义完此属性后,一定要有一个换行
- Start-Class
- 描述自定义 main 方法的全称
- org
- 存放了一些打包 SpringBoot 项目后的相关启动类
- 由于 SpringBoot 基于管理及安全性的考虑,打包使用 “项目代码与依赖包分离” 的方式(不同于以前将所有依赖包中的 .class 文件与项目的 .class 文件合并到一起的方式),因此打包后的 jar/war 包中依然包含了依赖的 jar 包,不符合 jar包 的规范,依赖的 jar包 无法通过默认的加载器进行加载
- 为了规避 jar文件规范,SpringBoot 使用自定义加载器去加载整个项目,于是入口就不再是编写项目时的 main 方法,而是使用
org.springframework.boot.loader.JarLauncher
类,在启动的时候创建自定义加载器去加载项目中的所有类 - 因此,打包后的 SpringBoot 项目,只有
org
文件夹中的类的类加载器是AppClassLoader
,BOOT-INF
文件夹中的类和依赖包的加载器是LaunchedURLClassLoader
war包的结构跟jar包结构差不多,只是多了几个目录(如 “WEB-INF/” 等)。
Spring Boot Loader的作用
SpringBoot在可执行jar包中定义了自己的一套规则,比如第三方依赖jar包在/lib目录下,jar包的URL路径使用自定义的规则并且这个规则需要使用org.springframework.boot.loader.jar.Handler处理器处理。它的Main-Class使用JarLauncher,如果是war包,使用WarLauncher执行。这些Launcher内部都会另起一个线程启动自定义的SpringApplication类。
这些特性通过 spring-boot-maven-plugin
插件打包完成。