相对于传统的JAVA可执行包(jar文件),SpringBoot的包结构有比较大的不一样。标准的JDK定义的jar文件里面是不能够有内嵌jar文件的,所以通常我们在执行一个jar文件里面的应用程序时,还需要通过-classpath来告诉JDK这个jar所依赖的所有的jar文件信息。而SpringBoot的build出来的包则允许将所有依赖的包打包到同一个jar里面,就是jar里面有jar,原因是spring-boot-loader重写了ClassLoader。
下面的SpringBoot官方文档对此行为的描述。
https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html
简单来说
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 其中SpringBoot提供的bootstrap的类是放到包的最外面,比如上面的org.springframework.boot.loader。 应用程序自己的代码则是需要放到BOOT-INF/classes目录下面;然后应用程序自己依赖的其它的jar文件则需要放到BOOT-INF/lib目录下。
当这个jar作为standardalone的程序运行时(没有放到container),SpringBoot会在生成的META-INF/MANIFEST.MF里面将Main-Class设置成org.springframework.boot.loader.JarLauncher,JarLauncher类会创建一个spring自己的ClassLoader: LaunchedURLClassLoader, 这个classloader 会就能通过URL来加载上面BOOT-INF/lib里面所依赖的包,并且通过反射Manifest里面的Start-Class里面定义的类,然后invoke这个类里面的main方法。
Manifest-Version: 1.0
Spring-Boot-Classes: BOOT-INF/classes/
Implementation-Title: gs-rest-serviceImplementation-Version: 0.1.0
Built-By: elichon
Start-Class: hello.Application
Created-By: Apache Maven 3.3.9
Implementation-URL: http://projects.spring.io/spring-boot/gs-rest-service/
Implementation-Vendor: Pivotal Software, Inc.
Implementation-Vendor-Id: org.springframeworkBuild-Jdk: 1.7.0_79
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 1.5.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Archiver-Version: Plexus Archiver
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
同样的,当用spring-boot来运行一个war包时,应当把依赖包放到WEB-INF/lib目录。然后对于应用程序依赖的jar,但传统的web container会提供的JAR,但需要把它们放到WEB-INF/lib-provided。这样就可以以下面的方式来启动这个war了: jar -jar example.war。