前两天有人问了一个问题:“宋哥,为什么我的SpringBoot项目中打包的jar被其他项目依赖后,总是报找不到该类的错误?”问题是因为我还没弄清楚可执行jar和普通jar有什么区别?宋弟兄今天就给大家讲讲这个问题。还有一个插件。SpringBoot默认打包的jar称为可执行jar。这种罐子不同于普通的罐子。普通的jar是无法通过java-jarxxx.jar命令执行的。普通jar主要依赖其他应用。,SpringBoot打出来的jar可以执行,但是不能被其他应用程序依赖。即使强行依赖,也获取不到里面的类。但是可执行jar并不是SpringBoot独有的,Java工程本身也可以打包成可执行jar。可能有些朋友会有疑惑。既然还要执行mvnpackage命令打包项目,为什么SpringBoot项目打包成可执行jar,而普通项目打包成不可执行jar呢?这里不得不提一下SpringBoot项目中的一个默认插件配置spring-boot-maven-plugin。这个打包插件有五个功能,从插件命令可以看出:五个功能分别是:build-info:生成项目的构建信息文件build-info.propertiesrepackage:这是默认目标。mvnpackage执行后,该命令重新打包生成可执行jar,并将mvnpackage生成的jar重命名为*.originSpringBoot应用生命周期的管理stop:这个是针对mvnintegration-test阶段,用于SpringBoot应用生命周期的管理这个功能,默认是repackage功能,其他功能需要开发者显式配置。打包repackage函数的作用是在打包的时候做一点额外的工作:首先,mvnpackage命令将项目打包成jar。这个jar是一个普通的jar,可以被其他项目依赖,但是不能通过执行repackage命令将第一步打包的jar重新打包,将第一步打包的jar重命名为*.jar使其成为可执行的jar。原始文件。例如:对于任意一个SpringBoot要打包的项目,可以执行mvnpackage命令,或者直接在IDEA中点击打包,如下:打包成功后,target中的文件如下:这里有两个文件,第一个restful-0.0.1-SNAPSHOT.jar表示打包成可执行jar,第二个restful-0.0.1-SNAPSHOT.jar.original是打包过程中重命名的jar。这是一个不可执行的jar,但是可以被其他项目依赖的jar。通过解压这两个文件,我们可以看出两者的区别。两个jar的对比可执行jar解压后目录如下:可以看到,在可执行jar中,我们自己的代码存在于BOOT-INF/classes/目录下,还有一个META-INF目录下,该目录下有一个MANIFEST.MF文件,打开文件,内容如下:Manifest-Version:1.0Implementation-Title:restfulImplementation-Version:0.0.1-SNAPSHOTStart-Class:org.javaboy.restful.RestfulApplicationSpring-Boot-Classes:BOOT-INF/classes/Spring-Boot-Lib:BOOT-INF/lib/Build-Jdk-Spec:1.8Spring-Boot-Version:2.1.6.RELEASECreated-By:MavenArchiver3.4.0Main-类:org.springframework。从boot.loader.JarLauncher可以看出,这里定义了一个Start-Class,它是可执行jar的入口类。Spring-Boot-Classes表示我们自己编译代码的位置,而Spring-Boot-Lib表示项目的依赖jar的位置。也就是说,如果要创建一个可执行的jar包,除了添加相关依赖外,还需要配置META-INF/MANIFEST.MF文件。这是可执行jar的结构,那非可执行jar的结构呢?我们先去掉默认后缀.original,然后重命名文件。重命名完成后,解压:解压后可以看到不可执行的jar根目录就相当于我们的classpath。解压后可以直接看到我们,里面还有一个META-INF/MANIFEST.MF文件,但是文件里没有定义启动类等。Manifest-Version:1.0Implementation-Title:restfulImplementation-Version:0.0.1-SNAPSHOTBuild-Jdk-Spec:1.8Created-By:MavenArchiver3.4.0注意这个jar不能执行,项目的依赖没有打包。从这里可以看出,这两个jar虽然都是jar包,但是内部结构完全不同,所以一个可以直接执行,一个可以被其他项目依赖。一次打包两个jar一般来说,SpringBoot可以直接打包成一个可执行的jar。不建议将SpringBoot作为一个普通的jar被其他项目依赖。如果有这样的需求,建议将依赖部分单独提取出来做一个普通的Maven工程,然后在SpringBoot中引用这个Maven工程。如果非要将SpringBoot打包成一个普通的jar,被其他项目依赖,从技术上讲,也是可以的。在spring-boot-maven-plugin插件中添加如下配置:
